mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-26 18:00:08 +01:00
Compare commits
341 commits
libevdev-1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be44b6e6a8 | ||
|
|
139b58e135 | ||
|
|
c6bf238c4e | ||
|
|
f3a9c2038d | ||
|
|
9289c9826c | ||
|
|
a30a461e82 | ||
|
|
d093b4752a | ||
|
|
ac0056961c | ||
|
|
d06abb81e5 | ||
|
|
cfd803566c | ||
|
|
1a8324aeb8 | ||
|
|
72fa564092 | ||
|
|
2342d8c9ee | ||
|
|
54c083378e | ||
|
|
5501633d51 | ||
|
|
080d1d097a | ||
|
|
414757317d | ||
|
|
fb5402020f | ||
|
|
de6ae19483 | ||
|
|
82560ca9d7 | ||
|
|
1ee2399ba8 | ||
|
|
d852e59dd0 | ||
|
|
8d8a3d8fc7 | ||
|
|
cd9bea914c | ||
|
|
179fc4d370 | ||
|
|
703999edec | ||
|
|
5db8e66bd3 | ||
|
|
2e0a0cd271 | ||
|
|
97d0e4d151 | ||
|
|
d21d826b63 | ||
|
|
d399abca1a | ||
|
|
d7139f1314 | ||
|
|
1cc8c6d491 | ||
|
|
f201583026 | ||
|
|
4582559b66 | ||
|
|
fb3741e0cd | ||
|
|
bb4404dd91 | ||
|
|
db0d4271ed | ||
|
|
689d1eb01c | ||
|
|
2eb0bb4be4 | ||
|
|
d8c491f57e | ||
|
|
54f4c054ea | ||
|
|
b2e12fe926 | ||
|
|
50ac79078e | ||
|
|
37f71a8493 | ||
|
|
6be54f75c8 | ||
|
|
427af9d248 | ||
|
|
6d0d778e59 | ||
|
|
ac3d44ee7a | ||
|
|
46ed9e53e4 | ||
|
|
1e9fb4fe02 | ||
|
|
1489287bf1 | ||
|
|
136efe0399 | ||
|
|
f45bc03d9f | ||
|
|
4f66455160 | ||
|
|
09fd1f4e66 | ||
|
|
7820dc8b08 | ||
|
|
df826a3c54 | ||
|
|
011946d446 | ||
|
|
ff4276398c | ||
|
|
1da836d0a9 | ||
|
|
b6c9dfd9d7 | ||
|
|
0afed6479d | ||
|
|
c6c4d33474 | ||
|
|
c9781f00f3 | ||
|
|
0c7e1d2f67 | ||
|
|
2d49be8303 | ||
|
|
c2eaaa171e | ||
|
|
de2daf8d36 | ||
|
|
8ced382eb8 | ||
|
|
f3c3b0a233 | ||
|
|
7c43e86944 | ||
|
|
066d9caf55 | ||
|
|
69403a63ed | ||
|
|
d03f9b6616 | ||
|
|
fdba5a41dd | ||
|
|
889fc01c81 | ||
|
|
8a4f45df5b | ||
|
|
9b918d316a | ||
|
|
5fc81553f5 | ||
|
|
a6970e1cec | ||
|
|
662c84d80e | ||
|
|
bb1cd0dd57 | ||
|
|
a53c6d1154 | ||
|
|
4e5babd7a1 | ||
|
|
8d70f44989 | ||
|
|
8855f1ac59 | ||
|
|
60d4f1b2ae | ||
|
|
7eae5e322c | ||
|
|
70881516f2 | ||
|
|
510bde8f47 | ||
|
|
7f53bcfab3 | ||
|
|
896d087a0e | ||
|
|
74dc7ff245 | ||
|
|
e6f3141eb6 | ||
|
|
a37d76b49b | ||
|
|
869fda7810 | ||
|
|
4226c7801b | ||
|
|
8e94375bc6 | ||
|
|
df677d954c | ||
|
|
f6c0a048c5 | ||
|
|
da2eea1dcb | ||
|
|
6ea230bc72 | ||
|
|
44b5c9bd9f | ||
|
|
b40675c701 | ||
|
|
cb5d56ab80 | ||
|
|
ed71864c4c | ||
|
|
fb6a84a52a | ||
|
|
a40e014eca | ||
|
|
cd8bde522f | ||
|
|
fd6c9b8ca0 | ||
|
|
1f54f82f70 | ||
|
|
4194023122 | ||
|
|
0af8c4054d | ||
|
|
8026722f86 | ||
|
|
800946a673 | ||
|
|
83e446225d | ||
|
|
153d8d0a5a | ||
|
|
1bf2b41d3f | ||
|
|
cca9093887 | ||
|
|
7ce82709aa | ||
|
|
db01b2d606 | ||
|
|
bcb79eed39 | ||
|
|
66113fe84f | ||
|
|
4c1b9f3c70 | ||
|
|
94a09a40bd | ||
|
|
2698867311 | ||
|
|
0ebdab6d6c | ||
|
|
4c87209826 | ||
|
|
55e70c5fd2 | ||
|
|
744a0e0f0b | ||
|
|
1354b29b17 | ||
|
|
7660726177 | ||
|
|
2e41b6778b | ||
|
|
c6a765199a | ||
|
|
521edcba27 | ||
|
|
f9302c18b7 | ||
|
|
325839e640 | ||
|
|
9ffed2f2f4 | ||
|
|
87a91718ef | ||
|
|
103f3870f0 | ||
|
|
fe8238a71a | ||
|
|
a1fe50635e | ||
|
|
68cdac7420 | ||
|
|
fc501b78ba | ||
|
|
7d2b4b5ffe | ||
|
|
bd8225286a | ||
|
|
1b1b446597 | ||
|
|
18ef5f76e0 | ||
|
|
a9d324f82b | ||
|
|
da5bfe22d2 | ||
|
|
6441b639aa | ||
|
|
bf72012921 | ||
|
|
59a9c6c5fb | ||
|
|
fcaa579bd0 | ||
|
|
468760ba11 | ||
|
|
edb5b92f89 | ||
|
|
13775b56e5 | ||
|
|
cda3dc664a | ||
|
|
c12af0864c | ||
|
|
2a51c15683 | ||
|
|
805421582f | ||
|
|
134b889724 | ||
|
|
82538647c1 | ||
|
|
15e0b024df | ||
|
|
e03cdd1d3f | ||
|
|
0e665a2780 | ||
|
|
db602d0d06 | ||
|
|
2038781bc2 | ||
|
|
f26679c6eb | ||
|
|
12211d452a | ||
|
|
fa0a3fc445 | ||
|
|
45c223d394 | ||
|
|
5a9368f4da | ||
|
|
283dfc07f9 | ||
|
|
f7ef246635 | ||
|
|
03f7b2be46 | ||
|
|
4b26eac8ad | ||
|
|
27aaba81d5 | ||
|
|
6ccee710bd | ||
|
|
e9ecb5cabc | ||
|
|
4c0eddfc74 | ||
|
|
d6c2b3d0de | ||
|
|
41de1b0e1a | ||
|
|
2056da9517 | ||
|
|
507bd1ee28 | ||
|
|
e38e3ae7c8 | ||
|
|
b64f94f9c4 | ||
|
|
b2ec3cb7d4 | ||
|
|
ada38025a2 | ||
|
|
f795694b2e | ||
|
|
d7098601c8 | ||
|
|
d654a8edf8 | ||
|
|
cd9fd458a5 | ||
|
|
ae0effd5ee | ||
|
|
88701829e7 | ||
|
|
e67826060b | ||
|
|
9fe2dfc8ef | ||
|
|
596ebd7acc | ||
|
|
2f9c40b5fb | ||
|
|
f2d4ef6cc4 | ||
|
|
12f9ec84d9 | ||
|
|
caf63dca41 | ||
|
|
6c88d8c1cf | ||
|
|
223909ed0b | ||
|
|
d209b66930 | ||
|
|
67b6e447e7 | ||
|
|
3e0a9e084d | ||
|
|
0dbcfed117 | ||
|
|
388644b22b | ||
|
|
50ebda0263 | ||
|
|
6430694715 | ||
|
|
c04f5bcec0 | ||
|
|
5501973320 | ||
|
|
757f2d4900 | ||
|
|
487d80a7fe | ||
|
|
c001fe50b0 | ||
|
|
977891bd88 | ||
|
|
4d4873d101 | ||
|
|
21ca8dba06 | ||
|
|
8666e6958d | ||
|
|
939076efc9 | ||
|
|
3d03038d78 | ||
|
|
4c8a7a265d | ||
|
|
0a66de813e | ||
|
|
201dfc38f9 | ||
|
|
ee2d35a90a | ||
|
|
6292354b44 | ||
|
|
90ff5a0cae | ||
|
|
9fec3228fb | ||
|
|
25cddcecd3 | ||
|
|
0af21e0e74 | ||
|
|
4fc12638d2 | ||
|
|
58559d9fec | ||
|
|
1014acedfc | ||
|
|
2af0b94623 | ||
|
|
28dbb3399a | ||
|
|
1f1bd4e2ce | ||
|
|
2f300eb6b5 | ||
|
|
06ef34c86b | ||
|
|
e74ba891f7 | ||
|
|
6668e0fe21 | ||
|
|
5b97b970c0 | ||
|
|
5b3659d468 | ||
|
|
ff8a5b065c | ||
|
|
925b2aa26d | ||
|
|
b65be7aa79 | ||
|
|
864f0c6829 | ||
|
|
74d4a3d11d | ||
|
|
6c4981393e | ||
|
|
9a5f44a605 | ||
|
|
2c6733fc67 | ||
|
|
779749b22c | ||
|
|
fce16d51a8 | ||
|
|
a2bb53262f | ||
|
|
da67db5f59 | ||
|
|
4d745caab4 | ||
|
|
1300c23792 | ||
|
|
71bf23cdc4 | ||
|
|
49206a2aba | ||
|
|
deb52eb52f | ||
|
|
d834a1f2b7 | ||
|
|
7ea9b09433 | ||
|
|
a68e91b172 | ||
|
|
c8be2b3260 | ||
|
|
cf645672dc | ||
|
|
ae7b6128a8 | ||
|
|
55d7375972 | ||
|
|
9fe185dd3d | ||
|
|
76662deeff | ||
|
|
951cd6a189 | ||
|
|
6852dadbca | ||
|
|
29628dc2c3 | ||
|
|
f293c11fec | ||
|
|
41e47b7043 | ||
|
|
1e605f6282 | ||
|
|
d9cfd143d0 | ||
|
|
812fc7096d | ||
|
|
35d6ce09d8 | ||
|
|
6a1f2e2ed2 | ||
|
|
a2ac0f0889 | ||
|
|
ad5142a1b3 | ||
|
|
c16d85b8b6 | ||
|
|
6345c1cca2 | ||
|
|
e4c3a8ee7a | ||
|
|
c4cfd7668a | ||
|
|
1f9e087dac | ||
|
|
805706a816 | ||
|
|
b642eddc31 | ||
|
|
83ce8eb5be | ||
|
|
bc5c72571d | ||
|
|
c3953e1bb8 | ||
|
|
3c6766c862 | ||
|
|
501f739564 | ||
|
|
7ae667ee89 | ||
|
|
fbeeef9cde | ||
|
|
6ff816163e | ||
|
|
a67d1964ff | ||
|
|
3799acd49e | ||
|
|
0f40ad8888 | ||
|
|
8df02686d3 | ||
|
|
e84897f29a | ||
|
|
0637d0237a | ||
|
|
022b2bc3b0 | ||
|
|
eefaca6f9f | ||
|
|
7ae59b1e9f | ||
|
|
c6e11a0a80 | ||
|
|
b08a3c70e5 | ||
|
|
7295576980 | ||
|
|
a9b3deb60f | ||
|
|
78322a9b45 | ||
|
|
abfb307e18 | ||
|
|
0b482b5f11 | ||
|
|
e7955544fe | ||
|
|
b13d67af9b | ||
|
|
a072277ba9 | ||
|
|
1ec01b1310 | ||
|
|
a155a977b7 | ||
|
|
24dafff909 | ||
|
|
1ee17e18ac | ||
|
|
d447a75e9e | ||
|
|
f7188aabc9 | ||
|
|
8a47a03044 | ||
|
|
452847a314 | ||
|
|
b261868b0a | ||
|
|
e938e0b959 | ||
|
|
61f0a0f9ad | ||
|
|
55c43b19cf | ||
|
|
94385480ff | ||
|
|
2a612997ab | ||
|
|
d05736765c | ||
|
|
0f346f3090 | ||
|
|
240ba34ebd | ||
|
|
0a5f884c58 | ||
|
|
df5ca55609 | ||
|
|
761687e995 | ||
|
|
911106230a | ||
|
|
4dd93f0108 | ||
|
|
7f2fffc0d9 | ||
|
|
98fd794693 | ||
|
|
e628bb938b |
76 changed files with 16744 additions and 3144 deletions
21
.editorconfig
Normal file
21
.editorconfig
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{c,h}]
|
||||||
|
indent_style = tab
|
||||||
|
tab_width = 8
|
||||||
|
|
||||||
|
[*.py]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
[*.{yaml,tmpl}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -31,8 +31,6 @@ mkinstalldirs
|
||||||
stamp-h?
|
stamp-h?
|
||||||
# Edit Compile Debug Document Distribute
|
# Edit Compile Debug Document Distribute
|
||||||
*~
|
*~
|
||||||
*.[0-9]
|
|
||||||
*.[0-9]x
|
|
||||||
*.bak
|
*.bak
|
||||||
*.bin
|
*.bin
|
||||||
core
|
core
|
||||||
|
|
|
||||||
692
.gitlab-ci.yml
Normal file
692
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,692 @@
|
||||||
|
########################################
|
||||||
|
# #
|
||||||
|
# THIS FILE IS GENERATED, DO NOT EDIT #
|
||||||
|
# #
|
||||||
|
########################################
|
||||||
|
|
||||||
|
.templates_sha: &template_sha e195d80f35b45cc73668be3767b923fd76c70ed5 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||||
|
|
||||||
|
include:
|
||||||
|
- project: 'freedesktop/ci-templates'
|
||||||
|
ref: *template_sha
|
||||||
|
file:
|
||||||
|
- '/templates/alpine.yml'
|
||||||
|
- '/templates/arch.yml'
|
||||||
|
- '/templates/debian.yml'
|
||||||
|
- '/templates/fedora.yml'
|
||||||
|
- '/templates/ubuntu.yml'
|
||||||
|
- '/templates/ci-fairy.yml'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- prep # rebuild the container images if there is a change
|
||||||
|
- build # for actually building and testing things in a container
|
||||||
|
- VM # for running the test suite in a VM
|
||||||
|
- autotools # distribution builds with autotools
|
||||||
|
- meson # distribution builds with meson
|
||||||
|
- tarballs # tarball builds
|
||||||
|
- container_clean # clean up unused container images
|
||||||
|
- merge-check # check for a merge request
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||||
|
when: never
|
||||||
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
|
||||||
|
variables:
|
||||||
|
# The upstrem repository we will check for images
|
||||||
|
FDO_UPSTREAM_REPO: libevdev/libevdev
|
||||||
|
GIT_DEPTH: 1
|
||||||
|
MESON_BUILDDIR: 'build dir'
|
||||||
|
|
||||||
|
.default_artifacts:
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- _build/test/test-suite.log
|
||||||
|
- $MESON_BUILDDIR/meson-logs/
|
||||||
|
expire_in: 1 week
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
junit: $MESON_BUILDDIR/*junit*.xml
|
||||||
|
|
||||||
|
.autotools_build:
|
||||||
|
extends:
|
||||||
|
- .default_artifacts
|
||||||
|
script:
|
||||||
|
- mkdir _build
|
||||||
|
- pushd _build > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules $CONFIGURE_FLAGS
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
- if ! [[ -z "$MAKE_ARGS" ]]; then make $MAKE_ARGS; fi
|
||||||
|
- popd > /dev/null
|
||||||
|
variables:
|
||||||
|
LIBEVDEV_SKIP_ROOT_TESTS: 1
|
||||||
|
|
||||||
|
.meson_build:
|
||||||
|
extends:
|
||||||
|
- .default_artifacts
|
||||||
|
script:
|
||||||
|
- .gitlab-ci/meson-build.sh --run-test
|
||||||
|
variables:
|
||||||
|
MESON_TEST_ARGS: '--no-suite=needs-uinput'
|
||||||
|
|
||||||
|
.fedora:40:
|
||||||
|
extends: .fdo.distribution-image@fedora
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: '40'
|
||||||
|
|
||||||
|
.fedora:41:
|
||||||
|
extends: .fdo.distribution-image@fedora
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: '41'
|
||||||
|
|
||||||
|
.ubuntu:24.10:
|
||||||
|
extends: .fdo.distribution-image@ubuntu
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: '24.10'
|
||||||
|
|
||||||
|
.debian:stable:
|
||||||
|
extends: .fdo.distribution-image@debian
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: 'stable'
|
||||||
|
|
||||||
|
.debian:sid:
|
||||||
|
extends: .fdo.distribution-image@debian
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: 'sid'
|
||||||
|
|
||||||
|
.arch:rolling:
|
||||||
|
extends: .fdo.distribution-image@arch
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: 'rolling'
|
||||||
|
|
||||||
|
.alpine:latest:
|
||||||
|
extends: .fdo.distribution-image@alpine
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '2024-11-25.0'
|
||||||
|
FDO_DISTRIBUTION_VERSION: 'latest'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# prep stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
# Re-generate the CI script and make sure it's the one currently checked in
|
||||||
|
# If this job fails, re-generate the gitlab-ci.yml script, see
|
||||||
|
# $SRCDIR/.gitlab-ci/generate-gitlab-ci.py
|
||||||
|
#
|
||||||
|
check-ci-script:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: prep
|
||||||
|
script:
|
||||||
|
- ci-fairy generate-template --verify && exit 0 || true
|
||||||
|
- echo "Committed gitlab-ci.yml differs from generated gitlab-ci.yml. Please verify"
|
||||||
|
- exit 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify that commit messages are as expected, signed-off, etc.
|
||||||
|
#
|
||||||
|
|
||||||
|
check-commit:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: prep
|
||||||
|
script:
|
||||||
|
- ci-fairy -vv check-commits --junit-xml=results.xml && exit 0 || true
|
||||||
|
- echo "Error checking the commit message format. Please verify"
|
||||||
|
- exit 1
|
||||||
|
except:
|
||||||
|
- master@libevdev/libevdev
|
||||||
|
variables:
|
||||||
|
GIT_DEPTH: 100
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
junit: results.xml
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify that the merge request has the allow-collaboration checkbox ticked
|
||||||
|
#
|
||||||
|
|
||||||
|
check-merge-request:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: merge-check
|
||||||
|
script:
|
||||||
|
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
|
||||||
|
artifacts:
|
||||||
|
when: on_failure
|
||||||
|
reports:
|
||||||
|
junit: results.xml
|
||||||
|
allow_failure: true
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||||
|
|
||||||
|
|
||||||
|
.fedora.packages:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: 'git gcc gcc-c++ meson automake autoconf libtool make pkgconfig python3 check-devel valgrind binutils doxygen xz clang-analyzer systemd-udev qemu-img qemu-system-x86-core qemu-system-aarch64-core jq python3-click python3-rich'
|
||||||
|
|
||||||
|
.ubuntu.packages:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: 'git gcc g++ meson automake autoconf libtool make pkg-config python3 check valgrind binutils doxygen xz-utils'
|
||||||
|
|
||||||
|
.debian.packages:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: 'git gcc g++ meson automake autoconf libtool make pkg-config python3 check valgrind binutils doxygen xz-utils'
|
||||||
|
|
||||||
|
.arch.packages:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: 'git gc meson automake autoconf libtool make pkgconfig python3 check valgrind binutils doxygen'
|
||||||
|
|
||||||
|
.alpine.packages:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: 'git gcc g++ meson automake autoconf libtool make pkgconfig python3 check-dev valgrind binutils doxygen xz linux-headers'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
fedora:40@container-prep:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
- .fedora.packages
|
||||||
|
- .fdo.container-build@fedora
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
fedora:41@container-prep:
|
||||||
|
extends:
|
||||||
|
- .fedora:41
|
||||||
|
- .fedora.packages
|
||||||
|
- .fdo.container-build@fedora
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
ubuntu:24.10@container-prep:
|
||||||
|
extends:
|
||||||
|
- .ubuntu:24.10
|
||||||
|
- .ubuntu.packages
|
||||||
|
- .fdo.container-build@ubuntu
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
debian:stable@container-prep:
|
||||||
|
extends:
|
||||||
|
- .debian:stable
|
||||||
|
- .debian.packages
|
||||||
|
- .fdo.container-build@debian
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
debian:sid@container-prep:
|
||||||
|
extends:
|
||||||
|
- .debian:sid
|
||||||
|
- .debian.packages
|
||||||
|
- .fdo.container-build@debian
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
arch:rolling@container-prep:
|
||||||
|
extends:
|
||||||
|
- .arch:rolling
|
||||||
|
- .arch.packages
|
||||||
|
- .fdo.container-build@arch
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
alpine:latest@container-prep:
|
||||||
|
extends:
|
||||||
|
- .alpine:latest
|
||||||
|
- .alpine.packages
|
||||||
|
- .fdo.container-build@alpine
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# container clean stage #
|
||||||
|
# run during the clean stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# This stage will look for the container images we currently have in
|
||||||
|
# the registry and will remove any that are not tagged with the provided
|
||||||
|
# $container_image:$tag
|
||||||
|
.container-clean:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: container_clean
|
||||||
|
script:
|
||||||
|
# Go to your Profile, Settings, Access Tokens
|
||||||
|
# Create a personal token with 'api' scope, copy the value.
|
||||||
|
# Go to CI/CD, Schedules, schedule a new monthly job (or edit the existing one)
|
||||||
|
# Define a variable of type File named AUTHFILE. Content is that token
|
||||||
|
# value.
|
||||||
|
- ci-fairy -v --authfile $AUTHFILE delete-image
|
||||||
|
--repository $FDO_DISTRIBUTION_NAME/$FDO_DISTRIBUTION_VERSION
|
||||||
|
--exclude-tag $FDO_DISTRIBUTION_TAG
|
||||||
|
dependencies: []
|
||||||
|
allow_failure: true
|
||||||
|
only:
|
||||||
|
- schedules
|
||||||
|
|
||||||
|
### fedora 40
|
||||||
|
fedora:40@container-clean:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
- .container-clean
|
||||||
|
needs: ["fedora:40@container-prep"]
|
||||||
|
|
||||||
|
### fedora 41
|
||||||
|
fedora:41@container-clean:
|
||||||
|
extends:
|
||||||
|
- .fedora:41
|
||||||
|
- .container-clean
|
||||||
|
needs: ["fedora:41@container-prep"]
|
||||||
|
|
||||||
|
### ubuntu 24.10
|
||||||
|
ubuntu:24.10@container-clean:
|
||||||
|
extends:
|
||||||
|
- .ubuntu:24.10
|
||||||
|
- .container-clean
|
||||||
|
needs: ["ubuntu:24.10@container-prep"]
|
||||||
|
|
||||||
|
### debian stable
|
||||||
|
debian:stable@container-clean:
|
||||||
|
extends:
|
||||||
|
- .debian:stable
|
||||||
|
- .container-clean
|
||||||
|
needs: ["debian:stable@container-prep"]
|
||||||
|
|
||||||
|
### debian sid
|
||||||
|
debian:sid@container-clean:
|
||||||
|
extends:
|
||||||
|
- .debian:sid
|
||||||
|
- .container-clean
|
||||||
|
needs: ["debian:sid@container-prep"]
|
||||||
|
|
||||||
|
### arch rolling
|
||||||
|
arch:rolling@container-clean:
|
||||||
|
extends:
|
||||||
|
- .arch:rolling
|
||||||
|
- .container-clean
|
||||||
|
needs: ["arch:rolling@container-prep"]
|
||||||
|
|
||||||
|
### alpine latest
|
||||||
|
alpine:latest@container-clean:
|
||||||
|
extends:
|
||||||
|
- .alpine:latest
|
||||||
|
- .container-clean
|
||||||
|
needs: ["alpine:latest@container-prep"]
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# build stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
.autotools-build@template:
|
||||||
|
extends:
|
||||||
|
- .autotools_build
|
||||||
|
stage: build
|
||||||
|
dependencies: []
|
||||||
|
variables:
|
||||||
|
MAKE_ARGS: "distcheck"
|
||||||
|
|
||||||
|
.meson-build@template:
|
||||||
|
extends:
|
||||||
|
- .meson_build
|
||||||
|
stage: build
|
||||||
|
dependencies: []
|
||||||
|
|
||||||
|
|
||||||
|
fedora:40@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['fedora:40@container-prep']
|
||||||
|
|
||||||
|
fedora:40@meson-build:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['fedora:40@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
fedora:41@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .fedora:41
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['fedora:41@container-prep']
|
||||||
|
|
||||||
|
fedora:41@meson-build:
|
||||||
|
extends:
|
||||||
|
- .fedora:41
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['fedora:41@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
ubuntu:24.10@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .ubuntu:24.10
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['ubuntu:24.10@container-prep']
|
||||||
|
|
||||||
|
ubuntu:24.10@meson-build:
|
||||||
|
extends:
|
||||||
|
- .ubuntu:24.10
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['ubuntu:24.10@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
debian:stable@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .debian:stable
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['debian:stable@container-prep']
|
||||||
|
|
||||||
|
debian:stable@meson-build:
|
||||||
|
extends:
|
||||||
|
- .debian:stable
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['debian:stable@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
debian:sid@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .debian:sid
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['debian:sid@container-prep']
|
||||||
|
|
||||||
|
debian:sid@meson-build:
|
||||||
|
extends:
|
||||||
|
- .debian:sid
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['debian:sid@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
arch:rolling@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .arch:rolling
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['arch:rolling@container-prep']
|
||||||
|
|
||||||
|
arch:rolling@meson-build:
|
||||||
|
extends:
|
||||||
|
- .arch:rolling
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['arch:rolling@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
alpine:latest@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .alpine:latest
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
needs: ['alpine:latest@container-prep']
|
||||||
|
|
||||||
|
alpine:latest@meson-build:
|
||||||
|
extends:
|
||||||
|
- .alpine:latest
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
needs: ['alpine:latest@container-prep']
|
||||||
|
|
||||||
|
|
||||||
|
# Build argument tests
|
||||||
|
#
|
||||||
|
# We only run the build option combinations on one image
|
||||||
|
# because they're supposed to fail equally on all
|
||||||
|
.fedora-custom-build@autotools-template:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: build
|
||||||
|
needs: ['fedora:40@container-prep']
|
||||||
|
|
||||||
|
no-valgrind:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y valgrind
|
||||||
|
|
||||||
|
no-check:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y check check-devel
|
||||||
|
|
||||||
|
no-doxygen:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen
|
||||||
|
variables:
|
||||||
|
MAKE_ARGS: '' # disable distcheck, requires doxygen
|
||||||
|
|
||||||
|
# doxygen is required for distcheck
|
||||||
|
no-doxygen-check-valgrind:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen valgrind check check-devel
|
||||||
|
variables:
|
||||||
|
MAKE_ARGS: '' # disable distcheck, requires doxygen
|
||||||
|
|
||||||
|
no-nm:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- mv /usr/bin/nm /usr/bin/nm.moved
|
||||||
|
|
||||||
|
enable-gcov:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
variables:
|
||||||
|
CONFIGURE_FLAGS: "--enable-gcov"
|
||||||
|
|
||||||
|
.fedora-custom-build@meson-template:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
- .meson-build@template
|
||||||
|
stage: build
|
||||||
|
needs: ['fedora:40@container-prep']
|
||||||
|
|
||||||
|
no-valgrind:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y valgrind
|
||||||
|
|
||||||
|
no-check:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y check check-devel
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: -Dtests=disabled
|
||||||
|
|
||||||
|
# doxygen is required for dist
|
||||||
|
no-doxygen:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: -Ddocumentation=disabled
|
||||||
|
NINJA_ARGS: ''
|
||||||
|
|
||||||
|
# doxygen is required for dist
|
||||||
|
no-doxygen-check-valgrind:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen valgrind check check-devel
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: -Dtests=disabled -Ddocumentation=disabled
|
||||||
|
NINJA_ARGS: ''
|
||||||
|
|
||||||
|
enable-gcov:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: '-Dcoverity=true'
|
||||||
|
|
||||||
|
scan-build:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
variables:
|
||||||
|
NINJA_ARGS: 'scan-build'
|
||||||
|
|
||||||
|
static-build:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
script:
|
||||||
|
- meson "$MESON_BUILDDIR" --default-library=static --prefix=$PWD/prefix-meson/
|
||||||
|
- ninja -C "$MESON_BUILDDIR" install
|
||||||
|
- ls -l $PWD/prefix-meson/lib64/libevdev.a
|
||||||
|
|
||||||
|
soname:
|
||||||
|
extends:
|
||||||
|
- .fedora:40
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- ./autogen.sh --prefix=$PWD/prefix-autotools/
|
||||||
|
- make install
|
||||||
|
- ls -l $PWD/prefix-autotools/lib/libevdev.so.2.3.0
|
||||||
|
- meson "$MESON_BUILDDIR" --prefix=$PWD/prefix-meson/
|
||||||
|
- ninja -C "$MESON_BUILDDIR" install
|
||||||
|
- ls -l $PWD/prefix-meson/lib64/libevdev.so.2.3.0
|
||||||
|
needs: ['fedora:40@container-prep']
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# VM stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
.check_tainted: &check_tainted |
|
||||||
|
# make sure the kernel is not tainted
|
||||||
|
if [[ "$(/app/vmctl exec cat /proc/sys/kernel/tainted)" -gt 0 ]];
|
||||||
|
then
|
||||||
|
echo tainted kernel ;
|
||||||
|
exit 1 ;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build on the host, then run a systemd service to execute the test suite
|
||||||
|
# inside the qemu VM handled by b2c
|
||||||
|
.build-in-b2c@template:
|
||||||
|
extends:
|
||||||
|
- .default_artifacts
|
||||||
|
tags:
|
||||||
|
- kvm
|
||||||
|
variables:
|
||||||
|
MESON_BUILDDIR: build_dir
|
||||||
|
B2C_KERNEL: https://gitlab.freedesktop.org/api/v4/projects/libevdev%2Fhid-tools/packages/generic/kernel-x86_64/v6.5/bzImage
|
||||||
|
B2C_IMAGE: $FDO_DISTRIBUTION_IMAGE
|
||||||
|
B2C_COMMAND: .gitlab-ci/start-in-systemd.sh
|
||||||
|
script:
|
||||||
|
# first build in the host container
|
||||||
|
- .gitlab-ci/meson-build.sh --skip-test
|
||||||
|
|
||||||
|
# pull b2c
|
||||||
|
- curl -L -o /app/boot2container https://gitlab.freedesktop.org/gfx-ci/boot2container/-/raw/2ff65156ba67fa8a0c309a4fc16c5df1a88a3844/vm2c.py
|
||||||
|
- chmod +x /app/boot2container
|
||||||
|
|
||||||
|
# runs the test suite only
|
||||||
|
- /app/boot2container
|
||||||
|
|
||||||
|
qemu:meson:
|
||||||
|
stage: VM
|
||||||
|
extends:
|
||||||
|
- .fdo.distribution-image@fedora
|
||||||
|
- .fedora:41
|
||||||
|
- .build-in-b2c@template
|
||||||
|
needs:
|
||||||
|
- "fedora:41@container-prep"
|
||||||
|
|
||||||
|
qemu:meson:valgrind:
|
||||||
|
extends:
|
||||||
|
- qemu:meson
|
||||||
|
variables:
|
||||||
|
MESON_TEST_ARGS: '--setup=valgrind'
|
||||||
|
|
||||||
|
|
||||||
|
meson-from-tarball:
|
||||||
|
extends:
|
||||||
|
- .fedora:41
|
||||||
|
stage: tarballs
|
||||||
|
script:
|
||||||
|
- export INSTALLDIR="$PWD/_inst"
|
||||||
|
- mkdir _build
|
||||||
|
- pushd _build > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules $CONFIGURE_FLAGS
|
||||||
|
- make
|
||||||
|
- make dist
|
||||||
|
- popd > /dev/null
|
||||||
|
- mkdir -p _tarball_dir
|
||||||
|
- tar xf _build/libevdev-*.tar.xz -C _tarball_dir
|
||||||
|
- pushd _tarball_dir/libevdev-*/ > /dev/null
|
||||||
|
- meson "$MESON_BUILDDIR" --prefix="$INSTALLDIR"
|
||||||
|
- meson test -C "$MESON_BUILDDIR" --no-suite="needs-uinput"
|
||||||
|
- ninja -C "$MESON_BUILDDIR" install
|
||||||
|
- popd > /dev/null
|
||||||
|
- ls -lR $INSTALLDIR
|
||||||
|
needs: ['fedora:41@container-prep']
|
||||||
|
|
||||||
|
autotools-from-tarball:
|
||||||
|
extends:
|
||||||
|
- .fedora:41
|
||||||
|
stage: tarballs
|
||||||
|
script:
|
||||||
|
- export INSTALLDIR="$PWD/_inst"
|
||||||
|
- meson "$MESON_BUILDDIR"
|
||||||
|
- meson dist -C "$MESON_BUILDDIR" --no-tests
|
||||||
|
- mkdir -p _tarball_dir
|
||||||
|
- tar xf "$MESON_BUILDDIR"/meson-dist/libevdev-*.xz -C _tarball_dir
|
||||||
|
- pushd _tarball_dir/libevdev-*/ > /dev/null
|
||||||
|
- mkdir _build
|
||||||
|
- pushd _build > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules --prefix="$INSTALLDIR" $CONFIGURE_FLAGS
|
||||||
|
- make
|
||||||
|
- make install
|
||||||
|
- make distcheck
|
||||||
|
- popd > /dev/null
|
||||||
|
- popd > /dev/null
|
||||||
|
- ls -lR $INSTALLDIR
|
||||||
|
variables:
|
||||||
|
LIBEVDEV_SKIP_ROOT_TESTS: 1
|
||||||
|
|
||||||
|
needs: ['fedora:41@container-prep']
|
||||||
486
.gitlab-ci/ci.template
Normal file
486
.gitlab-ci/ci.template
Normal file
|
|
@ -0,0 +1,486 @@
|
||||||
|
{# You're looking at the template here, so you can ignore the below
|
||||||
|
warning. This is the right file to edit #}
|
||||||
|
########################################
|
||||||
|
# #
|
||||||
|
# THIS FILE IS GENERATED, DO NOT EDIT #
|
||||||
|
# #
|
||||||
|
########################################
|
||||||
|
|
||||||
|
.templates_sha: &template_sha e195d80f35b45cc73668be3767b923fd76c70ed5 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||||
|
|
||||||
|
include:
|
||||||
|
- project: 'freedesktop/ci-templates'
|
||||||
|
ref: *template_sha
|
||||||
|
file:
|
||||||
|
{% for distribution in distributions|map(attribute='name')|unique()|sort() %}
|
||||||
|
- '/templates/{{distribution}}.yml'
|
||||||
|
{% endfor %}
|
||||||
|
- '/templates/ci-fairy.yml'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- prep # rebuild the container images if there is a change
|
||||||
|
- build # for actually building and testing things in a container
|
||||||
|
- VM # for running the test suite in a VM
|
||||||
|
- autotools # distribution builds with autotools
|
||||||
|
- meson # distribution builds with meson
|
||||||
|
- tarballs # tarball builds
|
||||||
|
- container_clean # clean up unused container images
|
||||||
|
- merge-check # check for a merge request
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||||
|
when: never
|
||||||
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
|
||||||
|
variables:
|
||||||
|
# The upstrem repository we will check for images
|
||||||
|
FDO_UPSTREAM_REPO: libevdev/libevdev
|
||||||
|
GIT_DEPTH: 1
|
||||||
|
MESON_BUILDDIR: 'build dir'
|
||||||
|
|
||||||
|
.default_artifacts:
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- _build/test/test-suite.log
|
||||||
|
- $MESON_BUILDDIR/meson-logs/
|
||||||
|
expire_in: 1 week
|
||||||
|
when: always
|
||||||
|
reports:
|
||||||
|
junit: $MESON_BUILDDIR/*junit*.xml
|
||||||
|
|
||||||
|
.autotools_build:
|
||||||
|
extends:
|
||||||
|
- .default_artifacts
|
||||||
|
script:
|
||||||
|
- mkdir _build
|
||||||
|
- pushd _build > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules $CONFIGURE_FLAGS
|
||||||
|
- make
|
||||||
|
- make check
|
||||||
|
- if ! [[ -z "$MAKE_ARGS" ]]; then make $MAKE_ARGS; fi
|
||||||
|
- popd > /dev/null
|
||||||
|
variables:
|
||||||
|
LIBEVDEV_SKIP_ROOT_TESTS: 1
|
||||||
|
|
||||||
|
.meson_build:
|
||||||
|
extends:
|
||||||
|
- .default_artifacts
|
||||||
|
script:
|
||||||
|
- .gitlab-ci/meson-build.sh --run-test
|
||||||
|
variables:
|
||||||
|
MESON_TEST_ARGS: '--no-suite=needs-uinput'
|
||||||
|
|
||||||
|
{# Generate templates for every distribution/version combination we want, any
|
||||||
|
job can then just extends: .name:version and the images will sort
|
||||||
|
themselves out. #}
|
||||||
|
{% for distro in distributions %}
|
||||||
|
{% for version in distro.versions %}
|
||||||
|
.{{distro.name}}:{{version}}:
|
||||||
|
extends: .fdo.distribution-image@{{distro.name}}
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_TAG: '{{distro.tag}}'
|
||||||
|
FDO_DISTRIBUTION_VERSION: '{{version}}'
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# prep stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
# Re-generate the CI script and make sure it's the one currently checked in
|
||||||
|
# If this job fails, re-generate the gitlab-ci.yml script, see
|
||||||
|
# $SRCDIR/.gitlab-ci/generate-gitlab-ci.py
|
||||||
|
#
|
||||||
|
check-ci-script:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: prep
|
||||||
|
script:
|
||||||
|
- ci-fairy generate-template --verify && exit 0 || true
|
||||||
|
- echo "Committed gitlab-ci.yml differs from generated gitlab-ci.yml. Please verify"
|
||||||
|
- exit 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify that commit messages are as expected, signed-off, etc.
|
||||||
|
#
|
||||||
|
|
||||||
|
check-commit:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: prep
|
||||||
|
script:
|
||||||
|
- ci-fairy -vv check-commits --junit-xml=results.xml && exit 0 || true
|
||||||
|
- echo "Error checking the commit message format. Please verify"
|
||||||
|
- exit 1
|
||||||
|
except:
|
||||||
|
- master@libevdev/libevdev
|
||||||
|
variables:
|
||||||
|
GIT_DEPTH: 100
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
junit: results.xml
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify that the merge request has the allow-collaboration checkbox ticked
|
||||||
|
#
|
||||||
|
|
||||||
|
check-merge-request:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: merge-check
|
||||||
|
script:
|
||||||
|
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
|
||||||
|
artifacts:
|
||||||
|
when: on_failure
|
||||||
|
reports:
|
||||||
|
junit: results.xml
|
||||||
|
allow_failure: true
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||||
|
|
||||||
|
|
||||||
|
{% for distro in distributions %}
|
||||||
|
.{{ distro.name }}.packages:
|
||||||
|
variables:
|
||||||
|
FDO_DISTRIBUTION_PACKAGES: '{{ ' '.join(distro.packages)}}'
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for distro in distributions %}
|
||||||
|
{% for version in distro.versions %}
|
||||||
|
|
||||||
|
# Pulls in the container from upstream or rebuilds it if missing
|
||||||
|
{{ distro.name }}:{{ version }}@container-prep:
|
||||||
|
extends:
|
||||||
|
- .{{ distro.name }}:{{ version }}
|
||||||
|
- .{{ distro.name}}.packages
|
||||||
|
- .fdo.container-build@{{ distro.name }}
|
||||||
|
stage: prep
|
||||||
|
variables:
|
||||||
|
GIT_STRATEGY: none
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# container clean stage #
|
||||||
|
# run during the clean stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# This stage will look for the container images we currently have in
|
||||||
|
# the registry and will remove any that are not tagged with the provided
|
||||||
|
# $container_image:$tag
|
||||||
|
.container-clean:
|
||||||
|
extends:
|
||||||
|
- .fdo.ci-fairy
|
||||||
|
stage: container_clean
|
||||||
|
script:
|
||||||
|
# Go to your Profile, Settings, Access Tokens
|
||||||
|
# Create a personal token with 'api' scope, copy the value.
|
||||||
|
# Go to CI/CD, Schedules, schedule a new monthly job (or edit the existing one)
|
||||||
|
# Define a variable of type File named AUTHFILE. Content is that token
|
||||||
|
# value.
|
||||||
|
- ci-fairy -v --authfile $AUTHFILE delete-image
|
||||||
|
--repository $FDO_DISTRIBUTION_NAME/$FDO_DISTRIBUTION_VERSION
|
||||||
|
--exclude-tag $FDO_DISTRIBUTION_TAG
|
||||||
|
dependencies: []
|
||||||
|
allow_failure: true
|
||||||
|
only:
|
||||||
|
- schedules
|
||||||
|
|
||||||
|
{% for distro in distributions %}
|
||||||
|
{% for version in distro.versions %}
|
||||||
|
### {{ distro.name }} {{ version }}
|
||||||
|
{{ distro.name }}:{{ version }}@container-clean:
|
||||||
|
extends:
|
||||||
|
- .{{ distro.name }}:{{ version }}
|
||||||
|
- .container-clean
|
||||||
|
needs: ["{{distro.name}}:{{version}}@container-prep"]
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# build stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
.autotools-build@template:
|
||||||
|
extends:
|
||||||
|
- .autotools_build
|
||||||
|
stage: build
|
||||||
|
dependencies: []
|
||||||
|
variables:
|
||||||
|
MAKE_ARGS: "distcheck"
|
||||||
|
|
||||||
|
.meson-build@template:
|
||||||
|
extends:
|
||||||
|
- .meson_build
|
||||||
|
stage: build
|
||||||
|
dependencies: []
|
||||||
|
|
||||||
|
{% for distro in distributions %}
|
||||||
|
{% for version in distro.versions %}
|
||||||
|
|
||||||
|
{{ distro.name }}:{{ version }}@autotools-build:
|
||||||
|
extends:
|
||||||
|
- .{{ distro.name }}:{{ version }}
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: autotools
|
||||||
|
{# Where we have extra_variables defined, add them to the list #}
|
||||||
|
{% if distro.build is defined and distro.build.extra_variables is defined %}
|
||||||
|
variables:
|
||||||
|
{% for key, value in distro.build.extra_variables.items() %}
|
||||||
|
{{ key }}: {{ value }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
needs: ['{{ distro.name }}:{{ version }}@container-prep']
|
||||||
|
|
||||||
|
{% if not distro.build is defined or distro.build.meson|default(True) %}
|
||||||
|
{{ distro.name }}:{{ version }}@meson-build:
|
||||||
|
extends:
|
||||||
|
- .{{ distro.name }}:{{ version }}
|
||||||
|
- .meson-build@template
|
||||||
|
stage: meson
|
||||||
|
{# Where we have extra_variables defined, add them to the list #}
|
||||||
|
{% if distro.build is defined and distro.build.extra_variables is defined %}
|
||||||
|
variables:
|
||||||
|
{% for key, value in distro.build.extra_variables.items() %}
|
||||||
|
{{ key }}: {{ value }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
needs: ['{{ distro.name }}:{{ version }}@container-prep']
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
# Build argument tests
|
||||||
|
#
|
||||||
|
# We only run the build option combinations on one image
|
||||||
|
# because they're supposed to fail equally on all
|
||||||
|
{% set custom_build_distro = distributions|selectattr("name", "equalto", "fedora")|first() %}
|
||||||
|
.fedora-custom-build@autotools-template:
|
||||||
|
extends:
|
||||||
|
- .{{custom_build_distro.name}}:{{custom_build_distro.versions|first()}}
|
||||||
|
- .autotools-build@template
|
||||||
|
stage: build
|
||||||
|
needs: ['{{custom_build_distro.name}}:{{custom_build_distro.versions|first()}}@container-prep']
|
||||||
|
|
||||||
|
no-valgrind:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y valgrind
|
||||||
|
|
||||||
|
no-check:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y check check-devel
|
||||||
|
|
||||||
|
no-doxygen:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen
|
||||||
|
variables:
|
||||||
|
MAKE_ARGS: '' # disable distcheck, requires doxygen
|
||||||
|
|
||||||
|
# doxygen is required for distcheck
|
||||||
|
no-doxygen-check-valgrind:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen valgrind check check-devel
|
||||||
|
variables:
|
||||||
|
MAKE_ARGS: '' # disable distcheck, requires doxygen
|
||||||
|
|
||||||
|
no-nm:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
before_script:
|
||||||
|
- mv /usr/bin/nm /usr/bin/nm.moved
|
||||||
|
|
||||||
|
enable-gcov:autotools:
|
||||||
|
extends: .fedora-custom-build@autotools-template
|
||||||
|
variables:
|
||||||
|
CONFIGURE_FLAGS: "--enable-gcov"
|
||||||
|
|
||||||
|
.fedora-custom-build@meson-template:
|
||||||
|
extends:
|
||||||
|
- .{{custom_build_distro.name}}:{{custom_build_distro.versions|first()}}
|
||||||
|
- .meson-build@template
|
||||||
|
stage: build
|
||||||
|
needs: ['{{custom_build_distro.name}}:{{custom_build_distro.versions|first()}}@container-prep']
|
||||||
|
|
||||||
|
no-valgrind:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y valgrind
|
||||||
|
|
||||||
|
no-check:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y check check-devel
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: -Dtests=disabled
|
||||||
|
|
||||||
|
# doxygen is required for dist
|
||||||
|
no-doxygen:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: -Ddocumentation=disabled
|
||||||
|
NINJA_ARGS: ''
|
||||||
|
|
||||||
|
# doxygen is required for dist
|
||||||
|
no-doxygen-check-valgrind:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
before_script:
|
||||||
|
- dnf remove -y doxygen valgrind check check-devel
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: -Dtests=disabled -Ddocumentation=disabled
|
||||||
|
NINJA_ARGS: ''
|
||||||
|
|
||||||
|
enable-gcov:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
variables:
|
||||||
|
MESON_ARGS: '-Dcoverity=true'
|
||||||
|
|
||||||
|
scan-build:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
variables:
|
||||||
|
NINJA_ARGS: 'scan-build'
|
||||||
|
|
||||||
|
static-build:meson:
|
||||||
|
extends: .fedora-custom-build@meson-template
|
||||||
|
script:
|
||||||
|
- meson "$MESON_BUILDDIR" --default-library=static --prefix=$PWD/prefix-meson/
|
||||||
|
- ninja -C "$MESON_BUILDDIR" install
|
||||||
|
- ls -l $PWD/prefix-meson/lib64/libevdev.a
|
||||||
|
|
||||||
|
soname:
|
||||||
|
extends:
|
||||||
|
- .{{custom_build_distro.name}}:{{custom_build_distro.versions|first()}}
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- ./autogen.sh --prefix=$PWD/prefix-autotools/
|
||||||
|
- make install
|
||||||
|
- ls -l $PWD/prefix-autotools/lib/libevdev.so.2.3.0
|
||||||
|
- meson "$MESON_BUILDDIR" --prefix=$PWD/prefix-meson/
|
||||||
|
- ninja -C "$MESON_BUILDDIR" install
|
||||||
|
- ls -l $PWD/prefix-meson/lib64/libevdev.so.2.3.0
|
||||||
|
needs: ['{{custom_build_distro.name}}:{{custom_build_distro.versions|first()}}@container-prep']
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
# #
|
||||||
|
# VM stage #
|
||||||
|
# #
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
.check_tainted: &check_tainted |
|
||||||
|
# make sure the kernel is not tainted
|
||||||
|
if [[ "$(/app/vmctl exec cat /proc/sys/kernel/tainted)" -gt 0 ]];
|
||||||
|
then
|
||||||
|
echo tainted kernel ;
|
||||||
|
exit 1 ;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build on the host, then run a systemd service to execute the test suite
|
||||||
|
# inside the qemu VM handled by b2c
|
||||||
|
.build-in-b2c@template:
|
||||||
|
extends:
|
||||||
|
- .default_artifacts
|
||||||
|
tags:
|
||||||
|
- kvm
|
||||||
|
variables:
|
||||||
|
MESON_BUILDDIR: build_dir
|
||||||
|
B2C_KERNEL: {{ b2c.kernel }}
|
||||||
|
B2C_IMAGE: $FDO_DISTRIBUTION_IMAGE
|
||||||
|
B2C_COMMAND: .gitlab-ci/start-in-systemd.sh
|
||||||
|
script:
|
||||||
|
# first build in the host container
|
||||||
|
- .gitlab-ci/meson-build.sh --skip-test
|
||||||
|
|
||||||
|
# pull b2c
|
||||||
|
- curl -L -o /app/boot2container https://gitlab.freedesktop.org/gfx-ci/boot2container/-/raw/{{b2c.version}}/vm2c.py
|
||||||
|
- chmod +x /app/boot2container
|
||||||
|
|
||||||
|
# runs the test suite only
|
||||||
|
- /app/boot2container
|
||||||
|
|
||||||
|
{% for distro in distributions if distro.use_for_qemu_tests %}
|
||||||
|
{% set version = "{}".format(distro.versions|last()) %}
|
||||||
|
qemu:meson:
|
||||||
|
stage: VM
|
||||||
|
extends:
|
||||||
|
- .fdo.distribution-image@{{distro.name}}
|
||||||
|
- .{{distro.name}}:{{version}}
|
||||||
|
- .build-in-b2c@template
|
||||||
|
needs:
|
||||||
|
- "{{distro.name}}:{{version}}@container-prep"
|
||||||
|
|
||||||
|
qemu:meson:valgrind:
|
||||||
|
extends:
|
||||||
|
- qemu:meson
|
||||||
|
variables:
|
||||||
|
MESON_TEST_ARGS: '--setup=valgrind'
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for distro in distributions if distro.use_for_tarball_tests %}
|
||||||
|
{% set version = "{}".format(distro.versions|last()) %}
|
||||||
|
meson-from-tarball:
|
||||||
|
extends:
|
||||||
|
- .{{distro.name}}:{{version}}
|
||||||
|
stage: tarballs
|
||||||
|
script:
|
||||||
|
- export INSTALLDIR="$PWD/_inst"
|
||||||
|
- mkdir _build
|
||||||
|
- pushd _build > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules $CONFIGURE_FLAGS
|
||||||
|
- make
|
||||||
|
- make dist
|
||||||
|
- popd > /dev/null
|
||||||
|
- mkdir -p _tarball_dir
|
||||||
|
- tar xf _build/libevdev-*.tar.xz -C _tarball_dir
|
||||||
|
- pushd _tarball_dir/libevdev-*/ > /dev/null
|
||||||
|
- meson "$MESON_BUILDDIR" --prefix="$INSTALLDIR"
|
||||||
|
- meson test -C "$MESON_BUILDDIR" --no-suite="needs-uinput"
|
||||||
|
- ninja -C "$MESON_BUILDDIR" install
|
||||||
|
- popd > /dev/null
|
||||||
|
- ls -lR $INSTALLDIR
|
||||||
|
needs: ['{{distro.name}}:{{version}}@container-prep']
|
||||||
|
|
||||||
|
autotools-from-tarball:
|
||||||
|
extends:
|
||||||
|
- .{{distro.name}}:{{version}}
|
||||||
|
stage: tarballs
|
||||||
|
script:
|
||||||
|
- export INSTALLDIR="$PWD/_inst"
|
||||||
|
- meson "$MESON_BUILDDIR"
|
||||||
|
- meson dist -C "$MESON_BUILDDIR" --no-tests
|
||||||
|
- mkdir -p _tarball_dir
|
||||||
|
- tar xf "$MESON_BUILDDIR"/meson-dist/libevdev-*.xz -C _tarball_dir
|
||||||
|
- pushd _tarball_dir/libevdev-*/ > /dev/null
|
||||||
|
- mkdir _build
|
||||||
|
- pushd _build > /dev/null
|
||||||
|
- ../autogen.sh --disable-silent-rules --prefix="$INSTALLDIR" $CONFIGURE_FLAGS
|
||||||
|
- make
|
||||||
|
- make install
|
||||||
|
- make distcheck
|
||||||
|
- popd > /dev/null
|
||||||
|
- popd > /dev/null
|
||||||
|
- ls -lR $INSTALLDIR
|
||||||
|
variables:
|
||||||
|
LIBEVDEV_SKIP_ROOT_TESTS: 1
|
||||||
|
|
||||||
|
needs: ['{{distro.name}}:{{version}}@container-prep']
|
||||||
|
{% endfor %}
|
||||||
125
.gitlab-ci/config.yml
Normal file
125
.gitlab-ci/config.yml
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
# This file contains the configuration for the gitlab ci.
|
||||||
|
# See the .gitlab-ci/generate-gitlab-ci.py file for more info
|
||||||
|
#
|
||||||
|
|
||||||
|
# We're happy to rebuild all containers when one changes.
|
||||||
|
.default_tag: &default_tag '2024-11-25.0'
|
||||||
|
|
||||||
|
distributions:
|
||||||
|
- name: fedora
|
||||||
|
tag: *default_tag
|
||||||
|
use_for_tarball_tests: true
|
||||||
|
# only one distro for qemu tests
|
||||||
|
use_for_qemu_tests: true
|
||||||
|
versions:
|
||||||
|
- '40'
|
||||||
|
- '41'
|
||||||
|
packages:
|
||||||
|
- git
|
||||||
|
- gcc
|
||||||
|
- gcc-c++
|
||||||
|
- meson
|
||||||
|
- automake
|
||||||
|
- autoconf
|
||||||
|
- libtool
|
||||||
|
- make
|
||||||
|
- pkgconfig
|
||||||
|
- python3
|
||||||
|
- check-devel
|
||||||
|
- valgrind
|
||||||
|
- binutils
|
||||||
|
- doxygen
|
||||||
|
- xz
|
||||||
|
- clang-analyzer
|
||||||
|
# below packages are for the qemu runs, so optional
|
||||||
|
- systemd-udev
|
||||||
|
- qemu-img
|
||||||
|
- qemu-system-x86-core
|
||||||
|
- qemu-system-aarch64-core
|
||||||
|
- jq
|
||||||
|
- python3-click
|
||||||
|
- python3-rich
|
||||||
|
- name: ubuntu
|
||||||
|
tag: *default_tag
|
||||||
|
versions:
|
||||||
|
- '24.10'
|
||||||
|
packages:
|
||||||
|
- git
|
||||||
|
- gcc
|
||||||
|
- g++
|
||||||
|
- meson
|
||||||
|
- automake
|
||||||
|
- autoconf
|
||||||
|
- libtool
|
||||||
|
- make
|
||||||
|
- pkg-config
|
||||||
|
- python3
|
||||||
|
- check
|
||||||
|
- valgrind
|
||||||
|
- binutils
|
||||||
|
- doxygen
|
||||||
|
- xz-utils
|
||||||
|
- name: debian
|
||||||
|
tag: *default_tag
|
||||||
|
versions:
|
||||||
|
- 'stable'
|
||||||
|
- 'sid'
|
||||||
|
packages:
|
||||||
|
- git
|
||||||
|
- gcc
|
||||||
|
- g++
|
||||||
|
- meson
|
||||||
|
- automake
|
||||||
|
- autoconf
|
||||||
|
- libtool
|
||||||
|
- make
|
||||||
|
- pkg-config
|
||||||
|
- python3
|
||||||
|
- check
|
||||||
|
- valgrind
|
||||||
|
- binutils
|
||||||
|
- doxygen
|
||||||
|
- xz-utils
|
||||||
|
- name: arch
|
||||||
|
tag: *default_tag
|
||||||
|
versions:
|
||||||
|
- 'rolling'
|
||||||
|
packages:
|
||||||
|
- git
|
||||||
|
- gc
|
||||||
|
- meson
|
||||||
|
- automake
|
||||||
|
- autoconf
|
||||||
|
- libtool
|
||||||
|
- make
|
||||||
|
- pkgconfig
|
||||||
|
- python3
|
||||||
|
- check
|
||||||
|
- valgrind
|
||||||
|
- binutils
|
||||||
|
- doxygen
|
||||||
|
- name: alpine
|
||||||
|
tag: *default_tag
|
||||||
|
versions:
|
||||||
|
- 'latest'
|
||||||
|
packages:
|
||||||
|
- git
|
||||||
|
- gcc
|
||||||
|
- g++
|
||||||
|
- meson
|
||||||
|
- automake
|
||||||
|
- autoconf
|
||||||
|
- libtool
|
||||||
|
- make
|
||||||
|
- pkgconfig
|
||||||
|
- python3
|
||||||
|
- check-dev
|
||||||
|
- valgrind
|
||||||
|
- binutils
|
||||||
|
- doxygen
|
||||||
|
- xz
|
||||||
|
- linux-headers
|
||||||
|
|
||||||
|
b2c:
|
||||||
|
version: 2ff65156ba67fa8a0c309a4fc16c5df1a88a3844
|
||||||
|
kernel: https://gitlab.freedesktop.org/api/v4/projects/libevdev%2Fhid-tools/packages/generic/kernel-x86_64/v6.5/bzImage
|
||||||
88
.gitlab-ci/meson-build.sh
Executable file
88
.gitlab-ci/meson-build.sh
Executable file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# This script is sourced from here:
|
||||||
|
# https://gitlab.freedesktop.org/whot/meson-helper
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
set -x
|
||||||
|
if [[ -f .meson_environment ]]; then
|
||||||
|
. .meson_environment
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If test args are set, we assume we want to run the tests
|
||||||
|
MESON_RUN_TEST="$MESON_TEST_ARGS"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--skip-setup)
|
||||||
|
shift
|
||||||
|
MESON_SKIP_SETUP="1"
|
||||||
|
;;
|
||||||
|
--skip-build)
|
||||||
|
shift
|
||||||
|
MESON_SKIP_BUILD="1"
|
||||||
|
;;
|
||||||
|
--skip-test)
|
||||||
|
shift
|
||||||
|
MESON_RUN_TEST=""
|
||||||
|
;;
|
||||||
|
--run-test)
|
||||||
|
shift
|
||||||
|
MESON_RUN_TEST="1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknow commandline argument $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$MESON_BUILDDIR" ]]; then
|
||||||
|
echo "\$MESON_BUILDDIR undefined."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# emulate a few gitlab variables to make it easier to
|
||||||
|
# run and debug locally.
|
||||||
|
if [[ -z "$CI_JOB_ID" ]] || [[ -z "$CI_JOB_NAME" ]]; then
|
||||||
|
echo "Missing \$CI_JOB_ID or \$CI_JOB_NAME".
|
||||||
|
CI_PROJECT_NAME=$(basename "$PWD")
|
||||||
|
CI_JOB_ID=$(date +%s)
|
||||||
|
CI_JOB_NAME="$CI_PROJECT_NAME-job-local"
|
||||||
|
echo "Simulating gitlab environment: "
|
||||||
|
echo " CI_JOB_ID=$CI_JOB_ID"
|
||||||
|
echo " CI_JOB_NAME=$CI_JOB_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$FDO_CI_CONCURRENT" ]]; then
|
||||||
|
jobcount="-j$FDO_CI_CONCURRENT"
|
||||||
|
export MESON_TESTTHREADS="$FDO_CI_CONCURRENT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "*************************************************"
|
||||||
|
echo "builddir: $MESON_BUILDDIR"
|
||||||
|
echo "meson args: $MESON_ARGS"
|
||||||
|
echo "ninja args: $NINJA_ARGS"
|
||||||
|
echo "meson test args: $MESON_TEST_ARGS"
|
||||||
|
echo "job count: ${jobcount-0}"
|
||||||
|
echo "*************************************************"
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ -z "$MESON_SKIP_SETUP" ]]; then
|
||||||
|
rm -rf "$MESON_BUILDDIR"
|
||||||
|
meson setup "$MESON_BUILDDIR" $MESON_ARGS
|
||||||
|
fi
|
||||||
|
meson configure "$MESON_BUILDDIR"
|
||||||
|
|
||||||
|
if [[ -z "$MESON_SKIP_BUILD" ]]; then
|
||||||
|
if [[ -n "$NINJA_ARGS" ]]; then
|
||||||
|
ninja_args="--ninja-args $NINJA_ARGS"
|
||||||
|
fi
|
||||||
|
meson compile -v -C "$MESON_BUILDDIR" $jobcount $ninja_args
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$MESON_RUN_TEST" ]]; then
|
||||||
|
meson test -C "$MESON_BUILDDIR" $MESON_TEST_ARGS --print-errorlogs
|
||||||
|
fi
|
||||||
69
.gitlab-ci/start-in-systemd.sh
Executable file
69
.gitlab-ci/start-in-systemd.sh
Executable file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
systemd_target=basic.target
|
||||||
|
post_command="/usr/bin/systemctl exit \$EXIT_STATUS"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--debug-mode)
|
||||||
|
shift
|
||||||
|
systemd_target=multi-user.target
|
||||||
|
post_command="echo you can now log in as root (no password) and then turn off by running \'/usr/bin/systemctl exit \$EXIT_STATUS\'"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknow commandline argument $1"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
WORKDIR=${FDO_DISTRIBUTION_WORKINGDIR:-$PWD}
|
||||||
|
B2C_WORKDIR=${FDO_B2C_WORKDIR:-/app}
|
||||||
|
|
||||||
|
# remove root password for debugging
|
||||||
|
sed -i 's/root:!locked::/root:::/' /etc/shadow
|
||||||
|
|
||||||
|
# create a libevdev test suite service
|
||||||
|
cat <<EOF > /etc/systemd/system/libevdev-testsuite.service
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=libevdev test suite
|
||||||
|
After=$systemd_target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
StandardOutput=journal+console
|
||||||
|
EnvironmentFile=$B2C_WORKDIR/.b2c_env
|
||||||
|
WorkingDirectory=$WORKDIR
|
||||||
|
ExecStart=$WORKDIR/.gitlab-ci/meson-build.sh --skip-setup --skip-build --run-test
|
||||||
|
|
||||||
|
# exit the container on termination
|
||||||
|
ExecStopPost=$post_command
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat /etc/systemd/system/libevdev-testsuite.service
|
||||||
|
|
||||||
|
# enable the service
|
||||||
|
systemctl enable libevdev-testsuite.service
|
||||||
|
|
||||||
|
# disable some services we don't need in the CI
|
||||||
|
systemctl mask network-online.target
|
||||||
|
systemctl mask network-pre.target
|
||||||
|
systemctl mask timers.target
|
||||||
|
systemctl mask dnf-makecache.timer
|
||||||
|
systemctl mask systemd-logind.service
|
||||||
|
systemctl mask rpmdb-migrate.service
|
||||||
|
systemctl mask systemd-network-generator.service
|
||||||
|
systemctl mask cryptsetup-pre.target
|
||||||
|
systemctl mask cryptsetup.target
|
||||||
|
|
||||||
|
#change default target
|
||||||
|
systemctl set-default $systemd_target
|
||||||
|
|
||||||
|
# start the system
|
||||||
|
exec /usr/sbin/init
|
||||||
222
CODING_STYLE.md
Normal file
222
CODING_STYLE.md
Normal file
|
|
@ -0,0 +1,222 @@
|
||||||
|
# Coding style
|
||||||
|
|
||||||
|
- Indentation in tabs, 8 characters wide, spaces after the tabs where
|
||||||
|
vertical alignment is required (see below)
|
||||||
|
|
||||||
|
**Note: this file uses spaces due to markdown rendering issues for tabs.
|
||||||
|
Code must be implemented using tabs.**
|
||||||
|
|
||||||
|
- Max line width 80ch, do not break up printed strings though
|
||||||
|
|
||||||
|
- Break up long lines at logical groupings, one line for each logical group
|
||||||
|
|
||||||
|
```c
|
||||||
|
int a = somelongname() +
|
||||||
|
someotherlongname();
|
||||||
|
|
||||||
|
if (a < 0 &&
|
||||||
|
(b > 20 & d < 10) &&
|
||||||
|
d != 0.0)
|
||||||
|
|
||||||
|
|
||||||
|
somelongfunctioncall(arg1, arg2,
|
||||||
|
otherarg);
|
||||||
|
```
|
||||||
|
|
||||||
|
- Function declarations: return type on separate line, {} on separate line,
|
||||||
|
arguments broken up as above.
|
||||||
|
|
||||||
|
```c
|
||||||
|
static inline int
|
||||||
|
foobar(int a, int b)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
somenamethatiswaytoolong(int a, int b,
|
||||||
|
int other)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `/* comments only */`, no `// comments`
|
||||||
|
|
||||||
|
- `variable_name`, not `VariableName` or `variableName`. same for functions.
|
||||||
|
|
||||||
|
- no typedefs of structs, enums, unions
|
||||||
|
|
||||||
|
- if it generates a compiler warning, it needs to be fixed
|
||||||
|
- if it generates a static checker warning, it needs to be fixed or
|
||||||
|
commented
|
||||||
|
|
||||||
|
- declare variables at the top, try to keep them as local as possible.
|
||||||
|
Exception: if the same variable is re-used in multiple blocks, declare it
|
||||||
|
at the top.
|
||||||
|
Exception: basic loop variables, e.g. for (int i = 0; ...)
|
||||||
|
|
||||||
|
```c
|
||||||
|
int a;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (foo) {
|
||||||
|
int b;
|
||||||
|
|
||||||
|
c = get_value();
|
||||||
|
usevalue(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bar) {
|
||||||
|
c = get_value();
|
||||||
|
useit(c);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- do not mix function invocations and variable definitions.
|
||||||
|
|
||||||
|
wrong:
|
||||||
|
|
||||||
|
```c
|
||||||
|
{
|
||||||
|
int a = foo();
|
||||||
|
int b = 7;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
right:
|
||||||
|
```c
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
int b = 7;
|
||||||
|
|
||||||
|
a = foo();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- if/else: { on the same line, no curly braces if both blocks are a single
|
||||||
|
statement. If either if or else block are multiple statements, both must
|
||||||
|
have curly braces.
|
||||||
|
|
||||||
|
```c
|
||||||
|
if (foo) {
|
||||||
|
blah();
|
||||||
|
bar();
|
||||||
|
} else {
|
||||||
|
a = 10;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- public functions MUST be doxygen-commented, use doxygen's `@foo` rather than
|
||||||
|
`\foo` notation
|
||||||
|
|
||||||
|
- `#include "config.h"` comes first, followed by system headers, followed by
|
||||||
|
external library headers, followed by internal headers.
|
||||||
|
sort alphabetically where it makes sense (specifically system headers)
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libevdev/libevdev.h>
|
||||||
|
|
||||||
|
#include "libevdev-int.h"
|
||||||
|
```
|
||||||
|
|
||||||
|
- goto jumps only to the end of the function, and only for good reasons
|
||||||
|
(usually cleanup). goto never jumps backwards
|
||||||
|
|
||||||
|
- Use stdbool.h's bool for booleans within the library (instead of `int`).
|
||||||
|
Exception: the public API uses int, not bool.
|
||||||
|
|
||||||
|
# Git commit message requirements
|
||||||
|
|
||||||
|
Our CI will check the commit messages for a few requirements. Below is the
|
||||||
|
list of what we expect from a git commit.
|
||||||
|
|
||||||
|
## Commit message content
|
||||||
|
|
||||||
|
A [good commit message](http://who-t.blogspot.com/2009/12/on-commit-messages.html) needs to
|
||||||
|
answer three questions:
|
||||||
|
|
||||||
|
- Why is it necessary? It may fix a bug, it may add a feature, it may
|
||||||
|
improve performance, reliability, stability, or just be a change for the
|
||||||
|
sake of correctness.
|
||||||
|
- How does it address the issue? For short obvious patches this part can be
|
||||||
|
omitted, but it should be a high level description of what the approach
|
||||||
|
was.
|
||||||
|
- What effects does the patch have? (In addition to the obvious ones, this
|
||||||
|
may include benchmarks, side effects, etc.)
|
||||||
|
|
||||||
|
These three questions establish the context for the actual code changes, put
|
||||||
|
reviewers and others into the frame of mind to look at the diff and check if
|
||||||
|
the approach chosen was correct. A good commit message also helps
|
||||||
|
maintainers to decide if a given patch is suitable for stable branches or
|
||||||
|
inclusion in a distribution.
|
||||||
|
|
||||||
|
## Developer Certificate of Origin
|
||||||
|
|
||||||
|
Your commit **must** be signed off with a line:
|
||||||
|
```
|
||||||
|
Signed-off-by: <your name> <your email address>
|
||||||
|
```
|
||||||
|
By signing off, you indicate the [developer certificate of origin](https://developercertificate.org/).
|
||||||
|
|
||||||
|
> By making a contribution to this project, I certify that:
|
||||||
|
>
|
||||||
|
> (a) The contribution was created in whole or in part by me and I
|
||||||
|
> have the right to submit it under the open source license
|
||||||
|
> indicated in the file; or
|
||||||
|
>
|
||||||
|
> (b) The contribution is based upon previous work that, to the best
|
||||||
|
> of my knowledge, is covered under an appropriate open source
|
||||||
|
> license and I have the right under that license to submit that
|
||||||
|
> work with modifications, whether created in whole or in part
|
||||||
|
> by me, under the same open source license (unless I am
|
||||||
|
> permitted to submit under a different license), as indicated
|
||||||
|
> in the file; or
|
||||||
|
>
|
||||||
|
> (c) The contribution was provided directly to me by some other
|
||||||
|
> person who certified (a), (b) or (c) and I have not modified
|
||||||
|
> it.
|
||||||
|
>
|
||||||
|
> (d) I understand and agree that this project and the contribution
|
||||||
|
> are public and that a record of the contribution (including all
|
||||||
|
> personal information I submit with it, including my sign-off) is
|
||||||
|
> maintained indefinitely and may be redistributed consistent with
|
||||||
|
> this project or the open source license(s) involved.
|
||||||
|
|
||||||
|
## Commit message format
|
||||||
|
|
||||||
|
The canonical git commit message format is:
|
||||||
|
|
||||||
|
```
|
||||||
|
one line as the subject line with a high-level note
|
||||||
|
|
||||||
|
full explanation of the patch follows after an empty line. This explanation
|
||||||
|
can be multiple paragraphs and is largely free-form. Markdown is not
|
||||||
|
supported.
|
||||||
|
|
||||||
|
You can include extra data where required like:
|
||||||
|
- benchmark one says 10s
|
||||||
|
- benchmark two says 12s
|
||||||
|
|
||||||
|
Signed-off-by: <your name> <your email>
|
||||||
|
```
|
||||||
|
|
||||||
|
The subject line is the first thing everyone sees about this commit, so make
|
||||||
|
sure it's on point.
|
||||||
|
|
||||||
|
## Commit message technical requirements
|
||||||
|
|
||||||
|
- The commit message should use present tense (not past tense). Do write
|
||||||
|
"change foo to bar", not "changed foo to bar".
|
||||||
|
- The text width of the commit should be 78 chars or less, especially the
|
||||||
|
subject line.
|
||||||
|
- The author and signed-off-by must be your real name and email address. We
|
||||||
|
do not accept the default `@users.noreply` gitlab addresses.
|
||||||
|
```
|
||||||
|
git config --global user.name Your Name
|
||||||
|
git config --global user.email your@email
|
||||||
|
```
|
||||||
35
COPYING
35
COPYING
|
|
@ -1,23 +1,26 @@
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
Copyright © 2013 Red Hat, Inc.
|
Copyright © 2013 Red Hat, Inc.
|
||||||
Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
||||||
|
|
||||||
Permission to use, copy, modify, distribute, and sell this software and its
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
documentation for any purpose is hereby granted without fee, provided that
|
of this software and associated documentation files (the "Software"), to
|
||||||
the above copyright notice appear in all copies and that both that copyright
|
deal in the Software without restriction, including without limitation the
|
||||||
notice and this permission notice appear in supporting documentation, and
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
that the name of the copyright holders not be used in advertising or
|
sell copies of the Software, and to permit persons to whom the Software is
|
||||||
publicity pertaining to distribution of the software without specific,
|
furnished to do so, subject to the following conditions:
|
||||||
written prior permission. The copyright holders make no representations
|
|
||||||
about the suitability of this software for any purpose. It is provided "as
|
|
||||||
is" without express or implied warranty.
|
|
||||||
|
|
||||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
The above copyright notice and this permission notice (including the next
|
||||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
paragraph) shall be included in all copies or substantial portions of the
|
||||||
EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
Software.
|
||||||
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
OF THIS SOFTWARE.
|
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.
|
||||||
|
|
||||||
The following license is from a Linux kernel header file and there is no GPL
|
The following license is from a Linux kernel header file and there is no GPL
|
||||||
code this package links to.
|
code this package links to.
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,4 @@ SUBDIRS = doc libevdev tools test
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = libevdev.pc
|
pkgconfig_DATA = libevdev.pc
|
||||||
|
|
||||||
EXTRA_DIST = libevdev.pc.in
|
EXTRA_DIST = libevdev.pc.in meson.build meson_options.txt
|
||||||
|
|
|
||||||
17
README.md
17
README.md
|
|
@ -5,18 +5,17 @@ libevdev is a wrapper library for evdev devices. it moves the common
|
||||||
tasks when dealing with evdev devices into a library and provides a library
|
tasks when dealing with evdev devices into a library and provides a library
|
||||||
interface to the callers, thus avoiding erroneous ioctls, etc.
|
interface to the callers, thus avoiding erroneous ioctls, etc.
|
||||||
|
|
||||||
git://git.freedesktop.org/git/libevdev
|
https://gitlab.freedesktop.org/libevdev/libevdev.git
|
||||||
http://cgit.freedesktop.org/libevdev/
|
|
||||||
|
|
||||||
The eventual goal is that libevdev wraps all ioctls available to evdev
|
|
||||||
devices, thus making direct access unnecessary.
|
|
||||||
|
|
||||||
Go here for the API documentation:
|
Go here for the API documentation:
|
||||||
http://www.freedesktop.org/software/libevdev/doc/latest/
|
http://www.freedesktop.org/software/libevdev/doc/latest/
|
||||||
|
|
||||||
File bugs in the freedesktop.org bugzilla:
|
File bugs in the freedesktop.org GitLab instance:
|
||||||
https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev
|
https://gitlab.freedesktop.org/libevdev/libevdev/issues/
|
||||||
|
|
||||||
Patches, questions and general comments should be submitted to the input-tools@lists.freedesktop.org
|
Patches should be submitted as merge requests in the GitLab instance:
|
||||||
mailing list:
|
https://gitlab.freedesktop.org/libevdev/libevdev/merge_requests/
|
||||||
|
|
||||||
|
Questions and general comments should be submitted to the
|
||||||
|
input-tools@lists.freedesktop.org mailing list:
|
||||||
http://lists.freedesktop.org/mailman/listinfo/input-tools
|
http://lists.freedesktop.org/mailman/listinfo/input-tools
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,8 @@ cd "$srcdir"
|
||||||
autoreconf -fvi || exit $?
|
autoreconf -fvi || exit $?
|
||||||
|
|
||||||
cd "$olddir"
|
cd "$olddir"
|
||||||
test -n "$NOCONFIGURE" || $srcdir/configure "$@"
|
|
||||||
|
git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
|
||||||
|
git config --local format.subjectPrefix "PATCH libevdev"
|
||||||
|
|
||||||
|
test -n "$NOCONFIGURE" || exec "$srcdir"/configure "$@"
|
||||||
|
|
|
||||||
78
configure.ac
78
configure.ac
|
|
@ -1,28 +1,14 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
# Copyright © 2013 Red Hat, Inc.
|
# Copyright © 2013 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
# documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
# the above copyright notice appear in all copies and that both that copyright
|
|
||||||
# notice and this permission notice appear in supporting documentation, and
|
|
||||||
# that the name of the copyright holders not be used in advertising or
|
|
||||||
# publicity pertaining to distribution of the software without specific,
|
|
||||||
# written prior permission. The copyright holders make no representations
|
|
||||||
# about the suitability of this software for any purpose. It is provided "as
|
|
||||||
# is" without express or implied warranty.
|
|
||||||
#
|
|
||||||
# THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
# EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
# OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
AC_PREREQ([2.62])
|
AC_PREREQ([2.62])
|
||||||
|
|
||||||
|
# change meson version too
|
||||||
AC_INIT([libevdev],
|
AC_INIT([libevdev],
|
||||||
[1.5.0],
|
[1.13.6],
|
||||||
[https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev],
|
[https://gitlab.freedesktop.org/libevdev/libevdev/issues/],
|
||||||
[libevdev],
|
[libevdev],
|
||||||
[http://freedesktop.org/wiki/Software/libevdev/])
|
[http://freedesktop.org/wiki/Software/libevdev/])
|
||||||
|
|
||||||
|
|
@ -32,17 +18,11 @@ AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_AUX_DIR([build-aux])
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
|
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz subdir-objects])
|
||||||
|
|
||||||
# Before making a release, the LIBEVDEV_LT_VERSION string should be
|
# DO NOT MODIFY THIS
|
||||||
# modified.
|
# Use symbol versioning instead.
|
||||||
# The string is of the form C:R:A.
|
LIBEVDEV_LT_VERSION=5:0:3
|
||||||
# - If interfaces have been changed or added, but binary compatibility has
|
|
||||||
# been preserved, change to C+1:0:A+1
|
|
||||||
# - If binary compatibility has been broken (eg removed or changed interfaces)
|
|
||||||
# change to C+1:0:0
|
|
||||||
# - If the interface is the same as the previous version, change to C:R+1:A
|
|
||||||
LIBEVDEV_LT_VERSION=3:12:1
|
|
||||||
AC_SUBST(LIBEVDEV_LT_VERSION)
|
AC_SUBST(LIBEVDEV_LT_VERSION)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -66,14 +46,22 @@ if test "x$lt_cv_prog_gnu_ld" = "xyes"; then
|
||||||
fi
|
fi
|
||||||
AC_SUBST([GNU_LD_FLAGS], $with_ldflags)
|
AC_SUBST([GNU_LD_FLAGS], $with_ldflags)
|
||||||
|
|
||||||
|
case "${host_os}" in
|
||||||
|
freebsd*)
|
||||||
|
AC_SUBST([OS], [freebsd])
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_SUBST([OS], [linux])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
AC_CHECK_LIB([m], [round])
|
||||||
|
|
||||||
PKG_PROG_PKG_CONFIG()
|
PKG_PROG_PKG_CONFIG()
|
||||||
PKG_CHECK_MODULES(CHECK, [check >= 0.9.9], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
|
PKG_CHECK_MODULES(CHECK, [check >= 0.9.9], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
|
||||||
if test "x$HAVE_CHECK" = "xyes"; then
|
if test "x$HAVE_CHECK" != "xyes"; then
|
||||||
AC_PATH_PROG(VALGRIND, [valgrind])
|
|
||||||
else
|
|
||||||
AC_MSG_WARN([check not found - skipping building unit tests])
|
AC_MSG_WARN([check not found - skipping building unit tests])
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
|
|
||||||
AM_CONDITIONAL(ENABLE_RUNTIME_TESTS, [test "x$HAVE_CHECK" = "xyes"])
|
AM_CONDITIONAL(ENABLE_RUNTIME_TESTS, [test "x$HAVE_CHECK" = "xyes"])
|
||||||
AM_CONDITIONAL(ENABLE_STATIC_LINK_TEST, [test "x$enable_static" = "xyes"])
|
AM_CONDITIONAL(ENABLE_STATIC_LINK_TEST, [test "x$enable_static" = "xyes"])
|
||||||
|
|
||||||
|
|
@ -115,7 +103,7 @@ AC_ARG_ENABLE([gcov],
|
||||||
AS_IF([test "x$enable_gcov" != "xno"],
|
AS_IF([test "x$enable_gcov" != "xno"],
|
||||||
[
|
[
|
||||||
GCOV_CFLAGS="-fprofile-arcs -ftest-coverage"
|
GCOV_CFLAGS="-fprofile-arcs -ftest-coverage"
|
||||||
GCOV_LDFLAGS="-fprofile-arcs -ftest-coverage"
|
GCOV_LDFLAGS="-lgcov"
|
||||||
enable_gcov=yes
|
enable_gcov=yes
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
@ -124,8 +112,27 @@ AC_SUBST([GCOV_CFLAGS])
|
||||||
AC_SUBST([GCOV_LDFLAGS])
|
AC_SUBST([GCOV_LDFLAGS])
|
||||||
AC_MSG_RESULT([$enable_gcov])
|
AC_MSG_RESULT([$enable_gcov])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to build with coverity support])
|
||||||
|
AC_ARG_ENABLE([coverity],
|
||||||
|
[AS_HELP_STRING([--enable-coverity],
|
||||||
|
[Whether to build with coverity support (default: disabled)])],
|
||||||
|
[],
|
||||||
|
[enable_coverity=no],
|
||||||
|
)
|
||||||
|
AS_IF([test "x$enable_coverity" != "xno"],
|
||||||
|
[
|
||||||
|
AC_DEFINE([_Float128], [__uint128_t], [Override for coverity])
|
||||||
|
AC_DEFINE([_Float32], [int], [Override for coverity])
|
||||||
|
AC_DEFINE([_Float32x], [int], [Override for coverity])
|
||||||
|
AC_DEFINE([_Float64], [long], [Override for coverity])
|
||||||
|
AC_DEFINE([_Float64x], [long], [Override for coverity])
|
||||||
|
enable_coverity=yes
|
||||||
|
],
|
||||||
|
)
|
||||||
|
AC_MSG_RESULT([$enable_coverity])
|
||||||
|
|
||||||
|
|
||||||
AM_PATH_PYTHON([2.6])
|
AM_PATH_PYTHON([2.6])
|
||||||
AC_PATH_PROG(CAT, [cat])
|
|
||||||
|
|
||||||
# nm to check for leaking symbols in the static library
|
# nm to check for leaking symbols in the static library
|
||||||
AC_PATH_PROG(NM, [nm])
|
AC_PATH_PROG(NM, [nm])
|
||||||
|
|
@ -162,5 +169,6 @@ AC_MSG_RESULT([
|
||||||
Build documentation ${have_doxygen}
|
Build documentation ${have_doxygen}
|
||||||
Enable unit-tests ${HAVE_CHECK}
|
Enable unit-tests ${HAVE_CHECK}
|
||||||
Enable profiling ${enable_gcov}
|
Enable profiling ${enable_gcov}
|
||||||
|
Enable coverity support ${enable_coverity}
|
||||||
Static library symbol check ${static_symbol_leaks_test}
|
Static library symbol check ${static_symbol_leaks_test}
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,27 @@ header_files = \
|
||||||
$(top_srcdir)/libevdev/libevdev.h \
|
$(top_srcdir)/libevdev/libevdev.h \
|
||||||
$(top_srcdir)/libevdev/libevdev-uinput.h
|
$(top_srcdir)/libevdev/libevdev-uinput.h
|
||||||
|
|
||||||
html/index.html: libevdev.doxygen $(header_files)
|
html/index.html: libevdev.doxygen style/libevdevdoxygen.css $(header_files)
|
||||||
$(AM_V_GEN)$(DOXYGEN) $<
|
$(AM_V_GEN)$(DOXYGEN) $<
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
$(AM_V_at)rm -rf html
|
$(AM_V_at)rm -rf html
|
||||||
|
|
||||||
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
doc_src= $(shell find html -type f -printf "html/%P\n" 2>/dev/null)
|
||||||
EXTRA_DIST = html/index.html $(doc_src) libevdev.css
|
style_src = \
|
||||||
|
style/bootstrap.css \
|
||||||
|
style/customdoxygen.css \
|
||||||
|
style/doxy-boot.js \
|
||||||
|
style/dynsections.js \
|
||||||
|
style/footer.html \
|
||||||
|
style/header.html \
|
||||||
|
style/layout.xml \
|
||||||
|
style/libevdevdoxygen.css \
|
||||||
|
style/LICENSE \
|
||||||
|
style/README.md \
|
||||||
|
style/style.css
|
||||||
|
|
||||||
|
EXTRA_DIST = html/index.html $(doc_src) $(style_src)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
227
doc/libevdev.css
227
doc/libevdev.css
|
|
@ -1,227 +0,0 @@
|
||||||
h1 {
|
|
||||||
font-size: 150%;
|
|
||||||
color: #354C7B;
|
|
||||||
border-bottom: 1px solid #879ECB;
|
|
||||||
font-weight: normal;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#titlearea {
|
|
||||||
width: 30%;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
padding: 0px 10px 15px 10px;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid #879ECB;
|
|
||||||
}
|
|
||||||
|
|
||||||
#projectname {
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 300%;
|
|
||||||
margin-top: 5px;
|
|
||||||
padding: 2px 0 0 0;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
color: #354C7B;
|
|
||||||
}
|
|
||||||
|
|
||||||
#projectnumber {
|
|
||||||
font-size: 100%;
|
|
||||||
color: #354C7B;
|
|
||||||
}
|
|
||||||
|
|
||||||
#projectbrief {
|
|
||||||
text-align: center;
|
|
||||||
margin-left: 20px;
|
|
||||||
margin-top: 5px;
|
|
||||||
padding: 2px 0 0 0;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
color: #354C7B;
|
|
||||||
}
|
|
||||||
|
|
||||||
#MSearchBox {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#titlearea table {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#navrow1, #navrow2, #navrow3, #navrow4, #navpath {
|
|
||||||
width: 600px;
|
|
||||||
width: -moz-max-content;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* in file list, appears under the nav bars */
|
|
||||||
.navpath ul, .navpath li {
|
|
||||||
width: 600px;
|
|
||||||
width: -moz-max-content;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
background-image: none;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navpath li.navelem a {
|
|
||||||
text-shadow: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tabs, .tabs2, .tabs3 {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* main page/modules/files tabs */
|
|
||||||
.tablist li {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* main page/modules/files link text */
|
|
||||||
.tablist a {
|
|
||||||
background-image: none;
|
|
||||||
background-repeat: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* main page/modules/files link text when hovering */
|
|
||||||
.tablist a:hover {
|
|
||||||
background-image: none;
|
|
||||||
background-repeat: none;
|
|
||||||
text-shadow: none;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* main page/modules/files currently selected */
|
|
||||||
.tablist li.current a {
|
|
||||||
background-image: none;
|
|
||||||
text-shadow: none;
|
|
||||||
color: black;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navpath {
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* libevdev documentation/modules/file list ... superfluous header */
|
|
||||||
div.header {
|
|
||||||
display: none;
|
|
||||||
width: -moz-max-content;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
background-image: none;
|
|
||||||
background-color: inherit;
|
|
||||||
font-size: 300%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* general text blocks */
|
|
||||||
.textblock {
|
|
||||||
width: 600px;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* code fragments should expand to what's needed */
|
|
||||||
.fragment {
|
|
||||||
width: -moz-max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* list of modules container */
|
|
||||||
div .directory{
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
width: 600px;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.directory td.entry {
|
|
||||||
width: 40%;
|
|
||||||
white-space: normal;
|
|
||||||
padding-left: 5px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory td.desc {
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.directory td.entry img {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2.groupheader {
|
|
||||||
width: -moz-max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* table for list of functions */
|
|
||||||
table.memberdecls {
|
|
||||||
width: -moz-max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.memitem {
|
|
||||||
width: -moz-max-content;
|
|
||||||
border-bottom: 1px solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* function prototype */
|
|
||||||
div.memproto {
|
|
||||||
background-image: none;
|
|
||||||
width: 600px;
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* function documentation */
|
|
||||||
div.memdoc {
|
|
||||||
background-image: none;
|
|
||||||
width: -moz-max-content;
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.contents {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
width: 600px;
|
|
||||||
width: -moz-max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
width: 580px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dl.return {
|
|
||||||
width: 480px;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
background-color: #F9FAFC;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
width: 600px;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.footer {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note, see also, returns */
|
|
||||||
dl.section {
|
|
||||||
width: 560px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.params {
|
|
||||||
width: 560px;
|
|
||||||
}
|
|
||||||
|
|
@ -11,9 +11,12 @@ INPUT = @top_srcdir@/libevdev/libevdev.h \
|
||||||
@top_srcdir@/libevdev/libevdev-uinput.h
|
@top_srcdir@/libevdev/libevdev-uinput.h
|
||||||
EXAMPLE_PATH = @top_srcdir@/include
|
EXAMPLE_PATH = @top_srcdir@/include
|
||||||
GENERATE_HTML = YES
|
GENERATE_HTML = YES
|
||||||
HTML_EXTRA_STYLESHEET = @srcdir@/libevdev.css
|
|
||||||
HTML_TIMESTAMP = YES
|
|
||||||
GENERATE_LATEX = NO
|
GENERATE_LATEX = NO
|
||||||
MACRO_EXPANSION = YES
|
MACRO_EXPANSION = YES
|
||||||
EXPAND_ONLY_PREDEF = YES
|
EXPAND_ONLY_PREDEF = YES
|
||||||
PREDEFINED = LIBEVDEV_ATTRIBUTE_PRINTF(f,a)=
|
PREDEFINED = LIBEVDEV_ATTRIBUTE_PRINTF(f,a)=
|
||||||
|
HTML_HEADER = "@srcdir@/style/header.html"
|
||||||
|
HTML_FOOTER = "@srcdir@/style/footer.html"
|
||||||
|
HTML_EXTRA_STYLESHEET = "@srcdir@/style/bootstrap.css" \
|
||||||
|
"@srcdir@/style/customdoxygen.css" \
|
||||||
|
"@srcdir@/style/libevdevdoxygen.css"
|
||||||
|
|
|
||||||
229
doc/style/LICENSE
Normal file
229
doc/style/LICENSE
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
These licenses apply to the doxygen documentation HTML style only. They do
|
||||||
|
not apply or affect libinput 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.
|
||||||
6
doc/style/README.md
Normal file
6
doc/style/README.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Doxygen-Bootstrap
|
||||||
|
This is a small project for integrating Doxygen output with Twitter Bootstrap.
|
||||||
|
|
||||||
|
See the Stratify Documentation for an example: https://stratifylabs.co/StratifyAPI/html/
|
||||||
|
|
||||||
|
The header.html and footer.html files in this repo are designed to be used with Jekyll and Github pages (specifically it is based on https://github.com/plusjade/jekyll-bootstrap/). Be sure to modify the header/footer html files so that they fit your needs. You can look at the source of https://stratifylabs.co/StratifyAPI/html/ to see what css and js files are used in the header.
|
||||||
7500
doc/style/bootstrap.css
vendored
Normal file
7500
doc/style/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load diff
254
doc/style/customdoxygen.css
Normal file
254
doc/style/customdoxygen.css
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
98
doc/style/doxy-boot.js
Normal file
98
doc/style/doxy-boot.js
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013-2016, Tyler Gilbert
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the <organization> nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$( document ).ready(function() {
|
||||||
|
|
||||||
|
$("div.headertitle").addClass("page-header");
|
||||||
|
$("div.title").addClass("h1");
|
||||||
|
|
||||||
|
$('li > a[href="index.html"] > span').before("<i class='fa fa-cog'></i> ");
|
||||||
|
$('li > a[href="index.html"] > span').text("Stratify Labs");
|
||||||
|
$('li > a[href="modules.html"] > span').before("<i class='fa fa-square'></i> ");
|
||||||
|
$('li > a[href="namespaces.html"] > span').before("<i class='fa fa-bars'></i> ");
|
||||||
|
$('li > a[href="annotated.html"] > span').before("<i class='fa fa-list-ul'></i> ");
|
||||||
|
$('li > a[href="classes.html"] > span').before("<i class='fa fa-book'></i> ");
|
||||||
|
$('li > a[href="inherits.html"] > span').before("<i class='fa fa-sitemap'></i> ");
|
||||||
|
$('li > a[href="functions.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||||
|
$('li > a[href="functions_func.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||||
|
$('li > a[href="functions_vars.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||||
|
$('li > a[href="functions_enum.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||||
|
$('li > a[href="functions_eval.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||||
|
$(".icona .icon").addClass("label label-danger");
|
||||||
|
$(".icona .icon").after(" ");
|
||||||
|
|
||||||
|
$('img[src="closed.png"]').before("<i class='fa fa-chevron-right'></i> ");
|
||||||
|
$('img[src="closed.png"]').hide();
|
||||||
|
|
||||||
|
$("div.qindex").css("margin-bottom", "3em");
|
||||||
|
$("div.textblock").css("margin-bottom", "3em");
|
||||||
|
$("table.memberdecls").css("margin-bottom", "3em");
|
||||||
|
$("table.memberdecls").css("margin-top", "3em");
|
||||||
|
|
||||||
|
|
||||||
|
$("span.arrow").replaceWith("<i class='fa fa-chevron-right'></i> ");
|
||||||
|
|
||||||
|
$("ul.tablist").addClass("nav nav-pills");
|
||||||
|
$("ul.tablist").css("margin-top", "0.5em");
|
||||||
|
$("ul.tablist").css("margin-bottom", "0.5em");
|
||||||
|
$("li.current").addClass("active");
|
||||||
|
$("iframe").attr("scrolling", "yes");
|
||||||
|
|
||||||
|
$("#nav-path > ul").addClass("breadcrumb");
|
||||||
|
|
||||||
|
$("table.params").addClass("table");
|
||||||
|
$("div.ingroups").wrapInner("<small></small>");
|
||||||
|
$("div.levels").css("margin", "0.5em");
|
||||||
|
$("div.levels > span").addClass("btn btn-default btn-xs");
|
||||||
|
$("div.levels > span").css("margin-right", "0.25em");
|
||||||
|
|
||||||
|
$("table.directory").addClass("table table-striped table-bordered");
|
||||||
|
$("[class^=separator]").remove();
|
||||||
|
|
||||||
|
$("div.summary > a").addClass("btn btn-default btn-xs");
|
||||||
|
$("table.fieldtable").addClass("table");
|
||||||
|
$(".fragment").addClass("well");
|
||||||
|
$(".memitem").addClass("panel panel-default");
|
||||||
|
$(".memproto").addClass("panel-heading");
|
||||||
|
$(".memdoc").addClass("panel-body");
|
||||||
|
$("span.mlabel").addClass("label label-info");
|
||||||
|
|
||||||
|
$("table.memberdecls").addClass("table table-bordered");
|
||||||
|
//$("[class^=memitem]").addClass("active");
|
||||||
|
|
||||||
|
$("div.ah").addClass("btn btn-default");
|
||||||
|
$("span.mlabels").addClass("pull-right");
|
||||||
|
$("table.mlabels").css("width", "100%")
|
||||||
|
$("td.mlabels-right").addClass("pull-right");
|
||||||
|
|
||||||
|
$("div.ttc").addClass("panel panel-info");
|
||||||
|
$("div.ttname").addClass("panel-heading");
|
||||||
|
$("div.ttdef,div.ttdoc,div.ttdeci").addClass("panel-body");
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
12
doc/style/dynsections.js
Normal file
12
doc/style/dynsections.js
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
function toggleVisibility(linkObj)
|
||||||
|
{var base=$(linkObj).attr('id');var summary=$('#'+base+'-summary');var content=$('#'+base+'-content');var trigger=$('#'+base+'-trigger');var src=$(trigger).attr('src');if(content.is(':visible')===true){content.hide();summary.show();$(linkObj).addClass('closed').removeClass('opened');$(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');}else{content.show();summary.hide();$(linkObj).removeClass('closed').addClass('opened');$(trigger).attr('src',src.substring(0,src.length-10)+'open.png');}
|
||||||
|
return false;}
|
||||||
|
function updateStripes()
|
||||||
|
{$('table.directory tr').removeClass('even').filter(':visible:even').addClass('even');}
|
||||||
|
function toggleLevel(level)
|
||||||
|
{$('table.directory tr').each(function(){var l=this.id.split('_').length-1;var i=$('#img'+this.id.substring(3));var a=$('#arr'+this.id.substring(3));if(l<level+1){i.removeClass('iconfopen iconfclosed').addClass('iconfopen');a.html('▼');$(this).show();}else if(l==level+1){i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');a.html('►');$(this).show();}else{$(this).hide();}});updateStripes();}
|
||||||
|
function toggleFolder(id)
|
||||||
|
{var currentRow=$('#row_'+id);var rows=currentRow.nextAll("tr");var re=new RegExp('^row_'+id+'\\d+_$',"i");var childRows=rows.filter(function(){return this.id.match(re);});if(childRows.filter(':first').is(':visible')===true){var currentRowSpans=currentRow.find("span");currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");currentRowSpans.filter(".arrow").html('►');rows.filter("[id^=row_"+id+"]").hide();}else{var currentRowSpans=currentRow.find("span");currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");currentRowSpans.filter(".arrow").html('▼');var childRowsSpans=childRows.find("span");childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");childRowsSpans.filter(".arrow").html('►');childRows.show();}
|
||||||
|
updateStripes();}
|
||||||
|
function toggleInherit(id)
|
||||||
|
{var rows=$('tr.inherit.'+id);var img=$('tr.inherit_header.'+id+' img');var src=$(img).attr('src');if(rows.filter(':first').is(':visible')===true){rows.css('display','none');$(img).attr('src',src.substring(0,src.length-8)+'closed.png');}else{rows.css('display','table-row');$(img).attr('src',src.substring(0,src.length-10)+'open.png');}}
|
||||||
26
doc/style/footer.html
Normal file
26
doc/style/footer.html
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<!-- 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>
|
||||||
40
doc/style/header.html
Normal file
40
doc/style/header.html
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
<!-- 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
|
||||||
|
<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 -->
|
||||||
183
doc/style/layout.xml
Normal file
183
doc/style/layout.xml
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
<doxygenlayout version="1.0">
|
||||||
|
<!-- Navigation index tabs for HTML output -->
|
||||||
|
<navindex>
|
||||||
|
<tab type="mainpage" visible="yes" title=""/>
|
||||||
|
<tab type="pages" visible="no" title="" intro=""/>
|
||||||
|
<tab type="modules" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="namespaces" visible="yes" title="">
|
||||||
|
<tab type="namespaces" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="namespacemembers" visible="yes" title="" intro=""/>
|
||||||
|
</tab>
|
||||||
|
<tab type="classes" visible="yes" title="">
|
||||||
|
<tab type="classlist" visible="yes" title="" intro=""/>
|
||||||
|
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
|
||||||
|
</tab>
|
||||||
|
<tab type="files" visible="no" title="">
|
||||||
|
<tab type="filelist" visible="no" title="" intro=""/>
|
||||||
|
<tab type="globals" visible="no" title="" intro=""/>
|
||||||
|
</tab>
|
||||||
|
<tab type="examples" visible="no" title="" intro=""/>
|
||||||
|
</navindex>
|
||||||
|
|
||||||
|
<!-- Layout definition for a class page -->
|
||||||
|
<class>
|
||||||
|
<briefdescription visible="no"/>
|
||||||
|
<inheritancegraph visible="$CLASS_GRAPH"/>
|
||||||
|
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
|
||||||
|
<allmemberslink visible="yes"/>
|
||||||
|
<detaileddescription title="Documentation"/>
|
||||||
|
<memberdecl>
|
||||||
|
<nestedclasses visible="yes" title=""/>
|
||||||
|
<publictypes title=""/>
|
||||||
|
<publicslots title=""/>
|
||||||
|
<signals title=""/>
|
||||||
|
<publicmethods title=""/>
|
||||||
|
<publicstaticmethods title=""/>
|
||||||
|
<publicattributes title=""/>
|
||||||
|
<publicstaticattributes title=""/>
|
||||||
|
<protectedtypes title=""/>
|
||||||
|
<protectedslots title=""/>
|
||||||
|
<protectedmethods title=""/>
|
||||||
|
<protectedstaticmethods title=""/>
|
||||||
|
<protectedattributes title=""/>
|
||||||
|
<protectedstaticattributes title=""/>
|
||||||
|
<packagetypes title=""/>
|
||||||
|
<packagemethods title=""/>
|
||||||
|
<packagestaticmethods title=""/>
|
||||||
|
<packageattributes title=""/>
|
||||||
|
<packagestaticattributes title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
<privatetypes title=""/>
|
||||||
|
<privateslots title=""/>
|
||||||
|
<privatemethods title=""/>
|
||||||
|
<privatestaticmethods title=""/>
|
||||||
|
<privateattributes title=""/>
|
||||||
|
<privatestaticattributes title=""/>
|
||||||
|
<friends title=""/>
|
||||||
|
<related title="" subtitle=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<memberdef>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<constructors title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<related title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<usedfiles visible="$SHOW_USED_FILES"/>
|
||||||
|
<authorsection visible="yes"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
<!-- Layout definition for a namespace page -->
|
||||||
|
<namespace>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<memberdecl>
|
||||||
|
<nestednamespaces visible="yes" title=""/>
|
||||||
|
<classes visible="yes" title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<memberdef>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<authorsection visible="yes"/>
|
||||||
|
</namespace>
|
||||||
|
|
||||||
|
<!-- Layout definition for a file page -->
|
||||||
|
<file>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<includes visible="$SHOW_INCLUDE_FILES"/>
|
||||||
|
<includegraph visible="$INCLUDE_GRAPH"/>
|
||||||
|
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
|
||||||
|
<sourcelink visible="no"/>
|
||||||
|
<memberdecl>
|
||||||
|
<classes visible="yes" title=""/>
|
||||||
|
<namespaces visible="yes" title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<detaileddescription title="Documentation"/>
|
||||||
|
<memberdef>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<authorsection/>
|
||||||
|
</file>
|
||||||
|
|
||||||
|
<!-- Layout definition for a group page -->
|
||||||
|
<group>
|
||||||
|
<groupgraph visible="$GROUP_GRAPHS"/>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<detaileddescription title="Documentation"/>
|
||||||
|
<memberdecl>
|
||||||
|
<classes visible="yes" title=""/>
|
||||||
|
<namespaces visible="yes" title=""/>
|
||||||
|
<dirs visible="yes" title=""/>
|
||||||
|
<nestedgroups visible="yes" title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<enumvalues title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<signals title=""/>
|
||||||
|
<publicslots title=""/>
|
||||||
|
<protectedslots title=""/>
|
||||||
|
<privateslots title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<friends title=""/>
|
||||||
|
<membergroups visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
|
||||||
|
<memberdef>
|
||||||
|
<pagedocs/>
|
||||||
|
<inlineclasses title=""/>
|
||||||
|
<defines title=""/>
|
||||||
|
<typedefs title=""/>
|
||||||
|
<enums title=""/>
|
||||||
|
<enumvalues title=""/>
|
||||||
|
<functions title=""/>
|
||||||
|
<variables title=""/>
|
||||||
|
<signals title=""/>
|
||||||
|
<publicslots title=""/>
|
||||||
|
<protectedslots title=""/>
|
||||||
|
<privateslots title=""/>
|
||||||
|
<events title=""/>
|
||||||
|
<properties title=""/>
|
||||||
|
<friends title=""/>
|
||||||
|
</memberdef>
|
||||||
|
<authorsection visible="yes"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- Layout definition for a directory page -->
|
||||||
|
<directory>
|
||||||
|
<briefdescription visible="yes"/>
|
||||||
|
<directorygraph visible="yes"/>
|
||||||
|
<memberdecl>
|
||||||
|
<dirs visible="yes"/>
|
||||||
|
<files visible="yes"/>
|
||||||
|
</memberdecl>
|
||||||
|
<detaileddescription title="Documentation"/>
|
||||||
|
</directory>
|
||||||
|
</doxygenlayout>
|
||||||
111
doc/style/libevdevdoxygen.css
Normal file
111
doc/style/libevdevdoxygen.css
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono");
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 200%;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title .ingroups {
|
||||||
|
font-size: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 150%;
|
||||||
|
color: #354C7B;
|
||||||
|
background: none;
|
||||||
|
border-bottom: 1px solid #879ECB;
|
||||||
|
font-size: 150%;
|
||||||
|
font-weight: normal;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
padding-left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm-dox li {
|
||||||
|
float:left;
|
||||||
|
border-top: 0;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm li, .sm a {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm, .sm ul, .sm li {
|
||||||
|
list-style: none;
|
||||||
|
display: block;
|
||||||
|
line-height: normal;
|
||||||
|
direction: ltr;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm, .sm *, .sm *::before, .sm *::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-nav {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main menu sub-items like file-list, etc */
|
||||||
|
#main-menu li ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paramname {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memtitle {
|
||||||
|
background-image: none;
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memproto {
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headertitle {
|
||||||
|
background-image: none;
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.header {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.fieldname {
|
||||||
|
font-family: 'Roboto Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fieldtable th {
|
||||||
|
background-image: none;
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
letter-spacing: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams {
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #2873b0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.navpath ul {
|
||||||
|
background-image: none;
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
173
doc/style/style.css
Normal file
173
doc/style/style.css
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
/* The standard CSS for doxygen */
|
||||||
|
|
||||||
|
pre.fragment {
|
||||||
|
padding: 4px 6px;
|
||||||
|
margin: 4px 8px 4px 2px;
|
||||||
|
overflow: auto;
|
||||||
|
word-wrap: break-word;
|
||||||
|
font-size: 12pt;
|
||||||
|
line-height: 125%;
|
||||||
|
font-family: monospace, fixed;
|
||||||
|
font-size: 110%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.fragment {
|
||||||
|
padding: 4px;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.line {
|
||||||
|
font-family: monospace, fixed;
|
||||||
|
font-size: 16px;
|
||||||
|
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;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.groupHeader {
|
||||||
|
margin-left: 16px;
|
||||||
|
margin-top: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.groupText {
|
||||||
|
margin-left: 16px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
td.indexkey {
|
||||||
|
background-color: #EBEFF6;
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid #C4CFE5;
|
||||||
|
margin: 2px 0px 2px 0;
|
||||||
|
padding: 2px 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.indexvalue {
|
||||||
|
background-color: #EBEFF6;
|
||||||
|
border: 1px solid #C4CFE5;
|
||||||
|
padding: 2px 10px;
|
||||||
|
margin: 2px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.memlist {
|
||||||
|
background-color: #EEF1F7;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.formulaDsp {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.formulaDsp {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
img.formulaInl {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.center {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.center img {
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
address.footer {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.footer {
|
||||||
|
border: 0px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||||
/*
|
/*
|
||||||
* Input event codes
|
* Input event codes
|
||||||
*
|
*
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
|
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
|
||||||
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
|
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
|
||||||
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
|
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
|
||||||
|
#define INPUT_PROP_PRESSUREPAD 0x07 /* pressure triggers clicks */
|
||||||
|
|
||||||
#define INPUT_PROP_MAX 0x1f
|
#define INPUT_PROP_MAX 0x1f
|
||||||
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
|
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
|
||||||
|
|
@ -277,7 +279,8 @@
|
||||||
#define KEY_PAUSECD 201
|
#define KEY_PAUSECD 201
|
||||||
#define KEY_PROG3 202
|
#define KEY_PROG3 202
|
||||||
#define KEY_PROG4 203
|
#define KEY_PROG4 203
|
||||||
#define KEY_DASHBOARD 204 /* AL Dashboard */
|
#define KEY_ALL_APPLICATIONS 204 /* AC Desktop Show All Applications */
|
||||||
|
#define KEY_DASHBOARD KEY_ALL_APPLICATIONS
|
||||||
#define KEY_SUSPEND 205
|
#define KEY_SUSPEND 205
|
||||||
#define KEY_CLOSE 206 /* AC Close */
|
#define KEY_CLOSE 206 /* AC Close */
|
||||||
#define KEY_PLAY 207
|
#define KEY_PLAY 207
|
||||||
|
|
@ -406,6 +409,7 @@
|
||||||
#define BTN_TOOL_MOUSE 0x146
|
#define BTN_TOOL_MOUSE 0x146
|
||||||
#define BTN_TOOL_LENS 0x147
|
#define BTN_TOOL_LENS 0x147
|
||||||
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
|
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
|
||||||
|
#define BTN_STYLUS3 0x149
|
||||||
#define BTN_TOUCH 0x14a
|
#define BTN_TOUCH 0x14a
|
||||||
#define BTN_STYLUS 0x14b
|
#define BTN_STYLUS 0x14b
|
||||||
#define BTN_STYLUS2 0x14c
|
#define BTN_STYLUS2 0x14c
|
||||||
|
|
@ -437,10 +441,12 @@
|
||||||
#define KEY_TITLE 0x171
|
#define KEY_TITLE 0x171
|
||||||
#define KEY_SUBTITLE 0x172
|
#define KEY_SUBTITLE 0x172
|
||||||
#define KEY_ANGLE 0x173
|
#define KEY_ANGLE 0x173
|
||||||
#define KEY_ZOOM 0x174
|
#define KEY_FULL_SCREEN 0x174 /* AC View Toggle */
|
||||||
|
#define KEY_ZOOM KEY_FULL_SCREEN
|
||||||
#define KEY_MODE 0x175
|
#define KEY_MODE 0x175
|
||||||
#define KEY_KEYBOARD 0x176
|
#define KEY_KEYBOARD 0x176
|
||||||
#define KEY_SCREEN 0x177
|
#define KEY_ASPECT_RATIO 0x177 /* HUTRR37: Aspect */
|
||||||
|
#define KEY_SCREEN KEY_ASPECT_RATIO
|
||||||
#define KEY_PC 0x178 /* Media Select Computer */
|
#define KEY_PC 0x178 /* Media Select Computer */
|
||||||
#define KEY_TV 0x179 /* Media Select TV */
|
#define KEY_TV 0x179 /* Media Select TV */
|
||||||
#define KEY_TV2 0x17a /* Media Select Cable */
|
#define KEY_TV2 0x17a /* Media Select Cable */
|
||||||
|
|
@ -511,6 +517,10 @@
|
||||||
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
|
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
|
||||||
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
|
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
|
||||||
#define KEY_IMAGES 0x1ba /* AL Image Browser */
|
#define KEY_IMAGES 0x1ba /* AL Image Browser */
|
||||||
|
#define KEY_NOTIFICATION_CENTER 0x1bc /* Show/hide the notification center */
|
||||||
|
#define KEY_PICKUP_PHONE 0x1bd /* Answer incoming call */
|
||||||
|
#define KEY_HANGUP_PHONE 0x1be /* Decline incoming call */
|
||||||
|
#define KEY_LINK_PHONE 0x1bf /* AL Phone Syncing */
|
||||||
|
|
||||||
#define KEY_DEL_EOL 0x1c0
|
#define KEY_DEL_EOL 0x1c0
|
||||||
#define KEY_DEL_EOS 0x1c1
|
#define KEY_DEL_EOS 0x1c1
|
||||||
|
|
@ -538,6 +548,7 @@
|
||||||
#define KEY_FN_F 0x1e2
|
#define KEY_FN_F 0x1e2
|
||||||
#define KEY_FN_S 0x1e3
|
#define KEY_FN_S 0x1e3
|
||||||
#define KEY_FN_B 0x1e4
|
#define KEY_FN_B 0x1e4
|
||||||
|
#define KEY_FN_RIGHT_SHIFT 0x1e5
|
||||||
|
|
||||||
#define KEY_BRL_DOT1 0x1f1
|
#define KEY_BRL_DOT1 0x1f1
|
||||||
#define KEY_BRL_DOT2 0x1f2
|
#define KEY_BRL_DOT2 0x1f2
|
||||||
|
|
@ -591,7 +602,14 @@
|
||||||
#define BTN_DPAD_LEFT 0x222
|
#define BTN_DPAD_LEFT 0x222
|
||||||
#define BTN_DPAD_RIGHT 0x223
|
#define BTN_DPAD_RIGHT 0x223
|
||||||
|
|
||||||
|
#define BTN_GRIPL 0x224
|
||||||
|
#define BTN_GRIPR 0x225
|
||||||
|
#define BTN_GRIPL2 0x226
|
||||||
|
#define BTN_GRIPR2 0x227
|
||||||
|
|
||||||
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
|
#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
|
||||||
|
#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */
|
||||||
|
#define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */
|
||||||
|
|
||||||
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
|
#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
|
||||||
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
|
#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
|
||||||
|
|
@ -600,10 +618,31 @@
|
||||||
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
|
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
|
||||||
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
|
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
|
||||||
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
|
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
|
||||||
|
#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */
|
||||||
|
#define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */
|
||||||
|
#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */
|
||||||
|
#define KEY_DICTATE 0x24a /* Start or Stop Voice Dictation Session (HUTRR99) */
|
||||||
|
#define KEY_CAMERA_ACCESS_ENABLE 0x24b /* Enables programmatic access to camera devices. (HUTRR72) */
|
||||||
|
#define KEY_CAMERA_ACCESS_DISABLE 0x24c /* Disables programmatic access to camera devices. (HUTRR72) */
|
||||||
|
#define KEY_CAMERA_ACCESS_TOGGLE 0x24d /* Toggles the current state of the camera access control. (HUTRR72) */
|
||||||
|
#define KEY_ACCESSIBILITY 0x24e /* Toggles the system bound accessibility UI/command (HUTRR116) */
|
||||||
|
#define KEY_DO_NOT_DISTURB 0x24f /* Toggles the system-wide "Do Not Disturb" control (HUTRR94)*/
|
||||||
|
|
||||||
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
|
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
|
||||||
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
|
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keycodes for hotkeys toggling the electronic privacy screen found on some
|
||||||
|
* laptops on/off. Note when the embedded-controller turns on/off the eprivacy
|
||||||
|
* screen itself then the state should be reported through drm connecter props:
|
||||||
|
* https://www.kernel.org/doc/html/latest/gpu/drm-kms.html#standard-connector-properties
|
||||||
|
* Except when implementing the drm connecter properties API is not possible
|
||||||
|
* because e.g. the firmware does not allow querying the presence and/or status
|
||||||
|
* of the eprivacy screen at boot.
|
||||||
|
*/
|
||||||
|
#define KEY_EPRIVACY_SCREEN_ON 0x252
|
||||||
|
#define KEY_EPRIVACY_SCREEN_OFF 0x253
|
||||||
|
|
||||||
#define KEY_KBDINPUTASSIST_PREV 0x260
|
#define KEY_KBDINPUTASSIST_PREV 0x260
|
||||||
#define KEY_KBDINPUTASSIST_NEXT 0x261
|
#define KEY_KBDINPUTASSIST_NEXT 0x261
|
||||||
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262
|
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262
|
||||||
|
|
@ -611,6 +650,142 @@
|
||||||
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
||||||
#define KEY_KBDINPUTASSIST_CANCEL 0x265
|
#define KEY_KBDINPUTASSIST_CANCEL 0x265
|
||||||
|
|
||||||
|
/* Diagonal movement keys */
|
||||||
|
#define KEY_RIGHT_UP 0x266
|
||||||
|
#define KEY_RIGHT_DOWN 0x267
|
||||||
|
#define KEY_LEFT_UP 0x268
|
||||||
|
#define KEY_LEFT_DOWN 0x269
|
||||||
|
|
||||||
|
#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */
|
||||||
|
/* Show Top Menu of the Media (e.g. DVD) */
|
||||||
|
#define KEY_MEDIA_TOP_MENU 0x26b
|
||||||
|
#define KEY_NUMERIC_11 0x26c
|
||||||
|
#define KEY_NUMERIC_12 0x26d
|
||||||
|
/*
|
||||||
|
* Toggle Audio Description: refers to an audio service that helps blind and
|
||||||
|
* visually impaired consumers understand the action in a program. Note: in
|
||||||
|
* some countries this is referred to as "Video Description".
|
||||||
|
*/
|
||||||
|
#define KEY_AUDIO_DESC 0x26e
|
||||||
|
#define KEY_3D_MODE 0x26f
|
||||||
|
#define KEY_NEXT_FAVORITE 0x270
|
||||||
|
#define KEY_STOP_RECORD 0x271
|
||||||
|
#define KEY_PAUSE_RECORD 0x272
|
||||||
|
#define KEY_VOD 0x273 /* Video on Demand */
|
||||||
|
#define KEY_UNMUTE 0x274
|
||||||
|
#define KEY_FASTREVERSE 0x275
|
||||||
|
#define KEY_SLOWREVERSE 0x276
|
||||||
|
/*
|
||||||
|
* Control a data application associated with the currently viewed channel,
|
||||||
|
* e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
|
||||||
|
*/
|
||||||
|
#define KEY_DATA 0x277
|
||||||
|
#define KEY_ONSCREEN_KEYBOARD 0x278
|
||||||
|
/* Electronic privacy screen control */
|
||||||
|
#define KEY_PRIVACY_SCREEN_TOGGLE 0x279
|
||||||
|
|
||||||
|
/* Select an area of screen to be copied */
|
||||||
|
#define KEY_SELECTIVE_SCREENSHOT 0x27a
|
||||||
|
|
||||||
|
/* Move the focus to the next or previous user controllable element within a UI container */
|
||||||
|
#define KEY_NEXT_ELEMENT 0x27b
|
||||||
|
#define KEY_PREVIOUS_ELEMENT 0x27c
|
||||||
|
|
||||||
|
/* Toggle Autopilot engagement */
|
||||||
|
#define KEY_AUTOPILOT_ENGAGE_TOGGLE 0x27d
|
||||||
|
|
||||||
|
/* Shortcut Keys */
|
||||||
|
#define KEY_MARK_WAYPOINT 0x27e
|
||||||
|
#define KEY_SOS 0x27f
|
||||||
|
#define KEY_NAV_CHART 0x280
|
||||||
|
#define KEY_FISHING_CHART 0x281
|
||||||
|
#define KEY_SINGLE_RANGE_RADAR 0x282
|
||||||
|
#define KEY_DUAL_RANGE_RADAR 0x283
|
||||||
|
#define KEY_RADAR_OVERLAY 0x284
|
||||||
|
#define KEY_TRADITIONAL_SONAR 0x285
|
||||||
|
#define KEY_CLEARVU_SONAR 0x286
|
||||||
|
#define KEY_SIDEVU_SONAR 0x287
|
||||||
|
#define KEY_NAV_INFO 0x288
|
||||||
|
#define KEY_BRIGHTNESS_MENU 0x289
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some keyboards have keys which do not have a defined meaning, these keys
|
||||||
|
* are intended to be programmed / bound to macros by the user. For most
|
||||||
|
* keyboards with these macro-keys the key-sequence to inject, or action to
|
||||||
|
* take, is all handled by software on the host side. So from the kernel's
|
||||||
|
* point of view these are just normal keys.
|
||||||
|
*
|
||||||
|
* The KEY_MACRO# codes below are intended for such keys, which may be labeled
|
||||||
|
* e.g. G1-G18, or S1 - S30. The KEY_MACRO# codes MUST NOT be used for keys
|
||||||
|
* where the marking on the key does indicate a defined meaning / purpose.
|
||||||
|
*
|
||||||
|
* The KEY_MACRO# codes MUST also NOT be used as fallback for when no existing
|
||||||
|
* KEY_FOO define matches the marking / purpose. In this case a new KEY_FOO
|
||||||
|
* define MUST be added.
|
||||||
|
*/
|
||||||
|
#define KEY_MACRO1 0x290
|
||||||
|
#define KEY_MACRO2 0x291
|
||||||
|
#define KEY_MACRO3 0x292
|
||||||
|
#define KEY_MACRO4 0x293
|
||||||
|
#define KEY_MACRO5 0x294
|
||||||
|
#define KEY_MACRO6 0x295
|
||||||
|
#define KEY_MACRO7 0x296
|
||||||
|
#define KEY_MACRO8 0x297
|
||||||
|
#define KEY_MACRO9 0x298
|
||||||
|
#define KEY_MACRO10 0x299
|
||||||
|
#define KEY_MACRO11 0x29a
|
||||||
|
#define KEY_MACRO12 0x29b
|
||||||
|
#define KEY_MACRO13 0x29c
|
||||||
|
#define KEY_MACRO14 0x29d
|
||||||
|
#define KEY_MACRO15 0x29e
|
||||||
|
#define KEY_MACRO16 0x29f
|
||||||
|
#define KEY_MACRO17 0x2a0
|
||||||
|
#define KEY_MACRO18 0x2a1
|
||||||
|
#define KEY_MACRO19 0x2a2
|
||||||
|
#define KEY_MACRO20 0x2a3
|
||||||
|
#define KEY_MACRO21 0x2a4
|
||||||
|
#define KEY_MACRO22 0x2a5
|
||||||
|
#define KEY_MACRO23 0x2a6
|
||||||
|
#define KEY_MACRO24 0x2a7
|
||||||
|
#define KEY_MACRO25 0x2a8
|
||||||
|
#define KEY_MACRO26 0x2a9
|
||||||
|
#define KEY_MACRO27 0x2aa
|
||||||
|
#define KEY_MACRO28 0x2ab
|
||||||
|
#define KEY_MACRO29 0x2ac
|
||||||
|
#define KEY_MACRO30 0x2ad
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some keyboards with the macro-keys described above have some extra keys
|
||||||
|
* for controlling the host-side software responsible for the macro handling:
|
||||||
|
* -A macro recording start/stop key. Note that not all keyboards which emit
|
||||||
|
* KEY_MACRO_RECORD_START will also emit KEY_MACRO_RECORD_STOP if
|
||||||
|
* KEY_MACRO_RECORD_STOP is not advertised, then KEY_MACRO_RECORD_START
|
||||||
|
* should be interpreted as a recording start/stop toggle;
|
||||||
|
* -Keys for switching between different macro (pre)sets, either a key for
|
||||||
|
* cycling through the configured presets or keys to directly select a preset.
|
||||||
|
*/
|
||||||
|
#define KEY_MACRO_RECORD_START 0x2b0
|
||||||
|
#define KEY_MACRO_RECORD_STOP 0x2b1
|
||||||
|
#define KEY_MACRO_PRESET_CYCLE 0x2b2
|
||||||
|
#define KEY_MACRO_PRESET1 0x2b3
|
||||||
|
#define KEY_MACRO_PRESET2 0x2b4
|
||||||
|
#define KEY_MACRO_PRESET3 0x2b5
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some keyboards have a buildin LCD panel where the contents are controlled
|
||||||
|
* by the host. Often these have a number of keys directly below the LCD
|
||||||
|
* intended for controlling a menu shown on the LCD. These keys often don't
|
||||||
|
* have any labeling so we just name them KEY_KBD_LCD_MENU#
|
||||||
|
*/
|
||||||
|
#define KEY_KBD_LCD_MENU1 0x2b8
|
||||||
|
#define KEY_KBD_LCD_MENU2 0x2b9
|
||||||
|
#define KEY_KBD_LCD_MENU3 0x2ba
|
||||||
|
#define KEY_KBD_LCD_MENU4 0x2bb
|
||||||
|
#define KEY_KBD_LCD_MENU5 0x2bc
|
||||||
|
|
||||||
|
/* Performance Boost key (Alienware)/G-Mode key (Dell) */
|
||||||
|
#define KEY_PERFORMANCE 0x2bd
|
||||||
|
|
||||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||||
|
|
@ -672,6 +847,16 @@
|
||||||
#define REL_DIAL 0x07
|
#define REL_DIAL 0x07
|
||||||
#define REL_WHEEL 0x08
|
#define REL_WHEEL 0x08
|
||||||
#define REL_MISC 0x09
|
#define REL_MISC 0x09
|
||||||
|
/*
|
||||||
|
* 0x0a is reserved and should not be used in input drivers.
|
||||||
|
* It was used by HID as REL_MISC+1 and userspace needs to detect if
|
||||||
|
* the next REL_* event is correct or is just REL_MISC + n.
|
||||||
|
* We define here REL_RESERVED so userspace can rely on it and detect
|
||||||
|
* the situation described above.
|
||||||
|
*/
|
||||||
|
#define REL_RESERVED 0x0a
|
||||||
|
#define REL_WHEEL_HI_RES 0x0b
|
||||||
|
#define REL_HWHEEL_HI_RES 0x0c
|
||||||
#define REL_MAX 0x0f
|
#define REL_MAX 0x0f
|
||||||
#define REL_CNT (REL_MAX+1)
|
#define REL_CNT (REL_MAX+1)
|
||||||
|
|
||||||
|
|
@ -705,9 +890,19 @@
|
||||||
#define ABS_TOOL_WIDTH 0x1c
|
#define ABS_TOOL_WIDTH 0x1c
|
||||||
|
|
||||||
#define ABS_VOLUME 0x20
|
#define ABS_VOLUME 0x20
|
||||||
|
#define ABS_PROFILE 0x21
|
||||||
|
|
||||||
#define ABS_MISC 0x28
|
#define ABS_MISC 0x28
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0x2e is reserved and should not be used in input drivers.
|
||||||
|
* It was used by HID as ABS_MISC+6 and userspace needs to detect if
|
||||||
|
* the next ABS_* event is correct or is just ABS_MISC + n.
|
||||||
|
* We define here ABS_RESERVED so userspace can rely on it and detect
|
||||||
|
* the situation described above.
|
||||||
|
*/
|
||||||
|
#define ABS_RESERVED 0x2e
|
||||||
|
|
||||||
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
|
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
|
||||||
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||||
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
|
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
|
||||||
|
|
@ -724,6 +919,7 @@
|
||||||
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
|
#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
|
||||||
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
|
#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
|
||||||
|
|
||||||
|
|
||||||
#define ABS_MAX 0x3f
|
#define ABS_MAX 0x3f
|
||||||
#define ABS_CNT (ABS_MAX+1)
|
#define ABS_CNT (ABS_MAX+1)
|
||||||
|
|
||||||
|
|
@ -748,7 +944,10 @@
|
||||||
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
||||||
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
||||||
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
|
#define SW_MUTE_DEVICE 0x0e /* set = device disabled */
|
||||||
#define SW_MAX 0x0f
|
#define SW_PEN_INSERTED 0x0f /* set = pen inserted */
|
||||||
|
#define SW_MACHINE_COVER 0x10 /* set = cover closed */
|
||||||
|
#define SW_USB_INSERT 0x11 /* set = USB audio device connected */
|
||||||
|
#define SW_MAX 0x11
|
||||||
#define SW_CNT (SW_MAX+1)
|
#define SW_CNT (SW_MAX+1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
513
include/linux/freebsd/input.h
Normal file
513
include/linux/freebsd/input.h
Normal file
|
|
@ -0,0 +1,513 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1999-2002 Vojtech Pavlik
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef _UAPI_INPUT_H
|
||||||
|
#define _UAPI_INPUT_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/ioccom.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "input-event-codes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The event structure itself
|
||||||
|
* Note that __USE_TIME_BITS64 is defined by libc based on
|
||||||
|
* application's request to use 64 bit time_t.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct input_event {
|
||||||
|
#if 1 /* (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__) */
|
||||||
|
struct timeval time;
|
||||||
|
#define input_event_sec time.tv_sec
|
||||||
|
#define input_event_usec time.tv_usec
|
||||||
|
#else
|
||||||
|
__kernel_ulong_t __sec;
|
||||||
|
#if defined(__sparc__) && defined(__arch64__)
|
||||||
|
unsigned int __usec;
|
||||||
|
unsigned int __pad;
|
||||||
|
#else
|
||||||
|
__kernel_ulong_t __usec;
|
||||||
|
#endif
|
||||||
|
#define input_event_sec __sec
|
||||||
|
#define input_event_usec __usec
|
||||||
|
#endif
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t code;
|
||||||
|
int32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EV_VERSION 0x010001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IOCTLs (0x00 - 0x7f)
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct input_id {
|
||||||
|
uint16_t bustype;
|
||||||
|
uint16_t vendor;
|
||||||
|
uint16_t product;
|
||||||
|
uint16_t version;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls
|
||||||
|
* @value: latest reported value for the axis.
|
||||||
|
* @minimum: specifies minimum value for the axis.
|
||||||
|
* @maximum: specifies maximum value for the axis.
|
||||||
|
* @fuzz: specifies fuzz value that is used to filter noise from
|
||||||
|
* the event stream.
|
||||||
|
* @flat: values that are within this value will be discarded by
|
||||||
|
* joydev interface and reported as 0 instead.
|
||||||
|
* @resolution: specifies resolution for the values reported for
|
||||||
|
* the axis.
|
||||||
|
*
|
||||||
|
* Note that input core does not clamp reported values to the
|
||||||
|
* [minimum, maximum] limits, such task is left to userspace.
|
||||||
|
*
|
||||||
|
* The default resolution for main axes (ABS_X, ABS_Y, ABS_Z)
|
||||||
|
* is reported in units per millimeter (units/mm), resolution
|
||||||
|
* for rotational axes (ABS_RX, ABS_RY, ABS_RZ) is reported
|
||||||
|
* in units per radian.
|
||||||
|
* When INPUT_PROP_ACCELEROMETER is set the resolution changes.
|
||||||
|
* The main axes (ABS_X, ABS_Y, ABS_Z) are then reported in
|
||||||
|
* in units per g (units/g) and in units per degree per second
|
||||||
|
* (units/deg/s) for rotational axes (ABS_RX, ABS_RY, ABS_RZ).
|
||||||
|
*/
|
||||||
|
struct input_absinfo {
|
||||||
|
int32_t value;
|
||||||
|
int32_t minimum;
|
||||||
|
int32_t maximum;
|
||||||
|
int32_t fuzz;
|
||||||
|
int32_t flat;
|
||||||
|
int32_t resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
|
||||||
|
* @scancode: scancode represented in machine-endian form.
|
||||||
|
* @len: length of the scancode that resides in @scancode buffer.
|
||||||
|
* @index: index in the keymap, may be used instead of scancode
|
||||||
|
* @flags: allows to specify how kernel should handle the request. For
|
||||||
|
* example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
|
||||||
|
* should perform lookup in keymap by @index instead of @scancode
|
||||||
|
* @keycode: key code assigned to this scancode
|
||||||
|
*
|
||||||
|
* The structure is used to retrieve and modify keymap data. Users have
|
||||||
|
* option of performing lookup either by @scancode itself or by @index
|
||||||
|
* in keymap entry. EVIOCGKEYCODE will also return scancode or index
|
||||||
|
* (depending on which element was used to perform lookup).
|
||||||
|
*/
|
||||||
|
struct input_keymap_entry {
|
||||||
|
#define INPUT_KEYMAP_BY_INDEX (1 << 0)
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t len;
|
||||||
|
uint16_t index;
|
||||||
|
uint32_t keycode;
|
||||||
|
uint8_t scancode[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct input_mask {
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t codes_size;
|
||||||
|
uint64_t codes_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
|
||||||
|
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
|
||||||
|
#define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */
|
||||||
|
#define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */
|
||||||
|
|
||||||
|
#define EVIOCGKEYCODE _IOWR('E', 0x04, unsigned int[2]) /* get keycode */
|
||||||
|
#define EVIOCGKEYCODE_V2 _IOWR('E', 0x04, struct input_keymap_entry)
|
||||||
|
#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */
|
||||||
|
#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry)
|
||||||
|
|
||||||
|
#define EVIOCGNAME(len) _IOC(IOC_OUT, 'E', 0x06, len) /* get device name */
|
||||||
|
#define EVIOCGPHYS(len) _IOC(IOC_OUT, 'E', 0x07, len) /* get physical location */
|
||||||
|
#define EVIOCGUNIQ(len) _IOC(IOC_OUT, 'E', 0x08, len) /* get unique identifier */
|
||||||
|
#define EVIOCGPROP(len) _IOC(IOC_OUT, 'E', 0x09, len) /* get device properties */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVIOCGMTSLOTS(len) - get MT slot values
|
||||||
|
* @len: size of the data buffer in bytes
|
||||||
|
*
|
||||||
|
* The ioctl buffer argument should be binary equivalent to
|
||||||
|
*
|
||||||
|
* struct input_mt_request_layout {
|
||||||
|
* uint32_t code;
|
||||||
|
* int32_t values[num_slots];
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* where num_slots is the (arbitrary) number of MT slots to extract.
|
||||||
|
*
|
||||||
|
* The ioctl size argument (len) is the size of the buffer, which
|
||||||
|
* should satisfy len = (num_slots + 1) * sizeof(int32_t). If len is
|
||||||
|
* too small to fit all available slots, the first num_slots are
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* Before the call, code is set to the wanted ABS_MT event type. On
|
||||||
|
* return, values[] is filled with the slot values for the specified
|
||||||
|
* ABS_MT code.
|
||||||
|
*
|
||||||
|
* If the request code is not an ABS_MT value, -EINVAL is returned.
|
||||||
|
*/
|
||||||
|
#define EVIOCGMTSLOTS(len) _IOC(IOC_INOUT, 'E', 0x0a, len)
|
||||||
|
|
||||||
|
#define EVIOCGKEY(len) _IOC(IOC_OUT, 'E', 0x18, len) /* get global key state */
|
||||||
|
#define EVIOCGLED(len) _IOC(IOC_OUT, 'E', 0x19, len) /* get all LEDs */
|
||||||
|
#define EVIOCGSND(len) _IOC(IOC_OUT, 'E', 0x1a, len) /* get all sounds status */
|
||||||
|
#define EVIOCGSW(len) _IOC(IOC_OUT, 'E', 0x1b, len) /* get all switch states */
|
||||||
|
|
||||||
|
#define EVIOCGBIT(ev,len) _IOC(IOC_OUT, 'E', 0x20 + (ev), len) /* get event bits */
|
||||||
|
#define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo) /* get abs value/limits */
|
||||||
|
#define EVIOCSABS(abs) _IOW('E', 0xc0 + (abs), struct input_absinfo) /* set abs value/limits */
|
||||||
|
|
||||||
|
#define EVIOCSFF _IOW('E', 0x80, struct ff_effect) /* send a force effect to a force feedback device */
|
||||||
|
#define EVIOCRMFF _IOWINT('E', 0x81) /* Erase a force effect */
|
||||||
|
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
|
||||||
|
|
||||||
|
#define EVIOCGRAB _IOWINT('E', 0x90) /* Grab/Release device */
|
||||||
|
#define EVIOCREVOKE _IOWINT('E', 0x91) /* Revoke device access */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVIOCGMASK - Retrieve current event mask
|
||||||
|
*
|
||||||
|
* This ioctl allows user to retrieve the current event mask for specific
|
||||||
|
* event type. The argument must be of type "struct input_mask" and
|
||||||
|
* specifies the event type to query, the address of the receive buffer and
|
||||||
|
* the size of the receive buffer.
|
||||||
|
*
|
||||||
|
* The event mask is a per-client mask that specifies which events are
|
||||||
|
* forwarded to the client. Each event code is represented by a single bit
|
||||||
|
* in the event mask. If the bit is set, the event is passed to the client
|
||||||
|
* normally. Otherwise, the event is filtered and will never be queued on
|
||||||
|
* the client's receive buffer.
|
||||||
|
*
|
||||||
|
* Event masks do not affect global state of the input device. They only
|
||||||
|
* affect the file descriptor they are applied to.
|
||||||
|
*
|
||||||
|
* The default event mask for a client has all bits set, i.e. all events
|
||||||
|
* are forwarded to the client. If the kernel is queried for an unknown
|
||||||
|
* event type or if the receive buffer is larger than the number of
|
||||||
|
* event codes known to the kernel, the kernel returns all zeroes for those
|
||||||
|
* codes.
|
||||||
|
*
|
||||||
|
* At maximum, codes_size bytes are copied.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with ENODEV in case the file is revoked, EFAULT
|
||||||
|
* if the receive-buffer points to invalid memory, or EINVAL if the kernel
|
||||||
|
* does not implement the ioctl.
|
||||||
|
*/
|
||||||
|
#define EVIOCGMASK _IOW('E', 0x92, struct input_mask) /* Get event-masks */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVIOCSMASK - Set event mask
|
||||||
|
*
|
||||||
|
* This ioctl is the counterpart to EVIOCGMASK. Instead of receiving the
|
||||||
|
* current event mask, this changes the client's event mask for a specific
|
||||||
|
* type. See EVIOCGMASK for a description of event-masks and the
|
||||||
|
* argument-type.
|
||||||
|
*
|
||||||
|
* This ioctl provides full forward compatibility. If the passed event type
|
||||||
|
* is unknown to the kernel, or if the number of event codes specified in
|
||||||
|
* the mask is bigger than what is known to the kernel, the ioctl is still
|
||||||
|
* accepted and applied. However, any unknown codes are left untouched and
|
||||||
|
* stay cleared. That means, the kernel always filters unknown codes
|
||||||
|
* regardless of what the client requests. If the new mask doesn't cover
|
||||||
|
* all known event-codes, all remaining codes are automatically cleared and
|
||||||
|
* thus filtered.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with ENODEV in case the file is revoked. EFAULT is
|
||||||
|
* returned if the receive-buffer points to invalid memory. EINVAL is returned
|
||||||
|
* if the kernel does not implement the ioctl.
|
||||||
|
*/
|
||||||
|
#define EVIOCSMASK _IOW('E', 0x93, struct input_mask) /* Set event-masks */
|
||||||
|
|
||||||
|
#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IDs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ID_BUS 0
|
||||||
|
#define ID_VENDOR 1
|
||||||
|
#define ID_PRODUCT 2
|
||||||
|
#define ID_VERSION 3
|
||||||
|
|
||||||
|
#define BUS_PCI 0x01
|
||||||
|
#define BUS_ISAPNP 0x02
|
||||||
|
#define BUS_USB 0x03
|
||||||
|
#define BUS_HIL 0x04
|
||||||
|
#define BUS_BLUETOOTH 0x05
|
||||||
|
#define BUS_VIRTUAL 0x06
|
||||||
|
|
||||||
|
#define BUS_ISA 0x10
|
||||||
|
#define BUS_I8042 0x11
|
||||||
|
#define BUS_XTKBD 0x12
|
||||||
|
#define BUS_RS232 0x13
|
||||||
|
#define BUS_GAMEPORT 0x14
|
||||||
|
#define BUS_PARPORT 0x15
|
||||||
|
#define BUS_AMIGA 0x16
|
||||||
|
#define BUS_ADB 0x17
|
||||||
|
#define BUS_I2C 0x18
|
||||||
|
#define BUS_HOST 0x19
|
||||||
|
#define BUS_GSC 0x1A
|
||||||
|
#define BUS_ATARI 0x1B
|
||||||
|
#define BUS_SPI 0x1C
|
||||||
|
#define BUS_RMI 0x1D
|
||||||
|
#define BUS_CEC 0x1E
|
||||||
|
#define BUS_INTEL_ISHTP 0x1F
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MT_TOOL types
|
||||||
|
*/
|
||||||
|
#define MT_TOOL_FINGER 0x00
|
||||||
|
#define MT_TOOL_PEN 0x01
|
||||||
|
#define MT_TOOL_PALM 0x02
|
||||||
|
#define MT_TOOL_DIAL 0x0a
|
||||||
|
#define MT_TOOL_MAX 0x0f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Values describing the status of a force-feedback effect
|
||||||
|
*/
|
||||||
|
#define FF_STATUS_STOPPED 0x00
|
||||||
|
#define FF_STATUS_PLAYING 0x01
|
||||||
|
#define FF_STATUS_MAX 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structures used in ioctls to upload effects to a device
|
||||||
|
* They are pieces of a bigger structure (called ff_effect)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All duration values are expressed in ms. Values above 32767 ms (0x7fff)
|
||||||
|
* should not be used and have unspecified results.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_replay - defines scheduling of the force-feedback effect
|
||||||
|
* @length: duration of the effect
|
||||||
|
* @delay: delay before effect should start playing
|
||||||
|
*/
|
||||||
|
struct ff_replay {
|
||||||
|
uint16_t length;
|
||||||
|
uint16_t delay;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_trigger - defines what triggers the force-feedback effect
|
||||||
|
* @button: number of the button triggering the effect
|
||||||
|
* @interval: controls how soon the effect can be re-triggered
|
||||||
|
*/
|
||||||
|
struct ff_trigger {
|
||||||
|
uint16_t button;
|
||||||
|
uint16_t interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_envelope - generic force-feedback effect envelope
|
||||||
|
* @attack_length: duration of the attack (ms)
|
||||||
|
* @attack_level: level at the beginning of the attack
|
||||||
|
* @fade_length: duration of fade (ms)
|
||||||
|
* @fade_level: level at the end of fade
|
||||||
|
*
|
||||||
|
* The @attack_level and @fade_level are absolute values; when applying
|
||||||
|
* envelope force-feedback core will convert to positive/negative
|
||||||
|
* value based on polarity of the default level of the effect.
|
||||||
|
* Valid range for the attack and fade levels is 0x0000 - 0x7fff
|
||||||
|
*/
|
||||||
|
struct ff_envelope {
|
||||||
|
uint16_t attack_length;
|
||||||
|
uint16_t attack_level;
|
||||||
|
uint16_t fade_length;
|
||||||
|
uint16_t fade_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_constant_effect - defines parameters of a constant force-feedback effect
|
||||||
|
* @level: strength of the effect; may be negative
|
||||||
|
* @envelope: envelope data
|
||||||
|
*/
|
||||||
|
struct ff_constant_effect {
|
||||||
|
int16_t level;
|
||||||
|
struct ff_envelope envelope;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_ramp_effect - defines parameters of a ramp force-feedback effect
|
||||||
|
* @start_level: beginning strength of the effect; may be negative
|
||||||
|
* @end_level: final strength of the effect; may be negative
|
||||||
|
* @envelope: envelope data
|
||||||
|
*/
|
||||||
|
struct ff_ramp_effect {
|
||||||
|
int16_t start_level;
|
||||||
|
int16_t end_level;
|
||||||
|
struct ff_envelope envelope;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_condition_effect - defines a spring or friction force-feedback effect
|
||||||
|
* @right_saturation: maximum level when joystick moved all way to the right
|
||||||
|
* @left_saturation: same for the left side
|
||||||
|
* @right_coeff: controls how fast the force grows when the joystick moves
|
||||||
|
* to the right
|
||||||
|
* @left_coeff: same for the left side
|
||||||
|
* @deadband: size of the dead zone, where no force is produced
|
||||||
|
* @center: position of the dead zone
|
||||||
|
*/
|
||||||
|
struct ff_condition_effect {
|
||||||
|
uint16_t right_saturation;
|
||||||
|
uint16_t left_saturation;
|
||||||
|
|
||||||
|
int16_t right_coeff;
|
||||||
|
int16_t left_coeff;
|
||||||
|
|
||||||
|
uint16_t deadband;
|
||||||
|
int16_t center;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_periodic_effect - defines parameters of a periodic force-feedback effect
|
||||||
|
* @waveform: kind of the effect (wave)
|
||||||
|
* @period: period of the wave (ms)
|
||||||
|
* @magnitude: peak value
|
||||||
|
* @offset: mean value of the wave (roughly)
|
||||||
|
* @phase: 'horizontal' shift
|
||||||
|
* @envelope: envelope data
|
||||||
|
* @custom_len: number of samples (FF_CUSTOM only)
|
||||||
|
* @custom_data: buffer of samples (FF_CUSTOM only)
|
||||||
|
*
|
||||||
|
* Known waveforms - FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP,
|
||||||
|
* FF_SAW_DOWN, FF_CUSTOM. The exact syntax FF_CUSTOM is undefined
|
||||||
|
* for the time being as no driver supports it yet.
|
||||||
|
*
|
||||||
|
* Note: the data pointed by custom_data is copied by the driver.
|
||||||
|
* You can therefore dispose of the memory after the upload/update.
|
||||||
|
*/
|
||||||
|
struct ff_periodic_effect {
|
||||||
|
uint16_t waveform;
|
||||||
|
uint16_t period;
|
||||||
|
int16_t magnitude;
|
||||||
|
int16_t offset;
|
||||||
|
uint16_t phase;
|
||||||
|
|
||||||
|
struct ff_envelope envelope;
|
||||||
|
|
||||||
|
uint32_t custom_len;
|
||||||
|
int16_t *custom_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
|
||||||
|
* @strong_magnitude: magnitude of the heavy motor
|
||||||
|
* @weak_magnitude: magnitude of the light one
|
||||||
|
*
|
||||||
|
* Some rumble pads have two motors of different weight. Strong_magnitude
|
||||||
|
* represents the magnitude of the vibration generated by the heavy one.
|
||||||
|
*/
|
||||||
|
struct ff_rumble_effect {
|
||||||
|
uint16_t strong_magnitude;
|
||||||
|
uint16_t weak_magnitude;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_effect - defines force feedback effect
|
||||||
|
* @type: type of the effect (FF_CONSTANT, FF_PERIODIC, FF_RAMP, FF_SPRING,
|
||||||
|
* FF_FRICTION, FF_DAMPER, FF_RUMBLE, FF_INERTIA, or FF_CUSTOM)
|
||||||
|
* @id: an unique id assigned to an effect
|
||||||
|
* @direction: direction of the effect
|
||||||
|
* @trigger: trigger conditions (struct ff_trigger)
|
||||||
|
* @replay: scheduling of the effect (struct ff_replay)
|
||||||
|
* @u: effect-specific structure (one of ff_constant_effect, ff_ramp_effect,
|
||||||
|
* ff_periodic_effect, ff_condition_effect, ff_rumble_effect) further
|
||||||
|
* defining effect parameters
|
||||||
|
*
|
||||||
|
* This structure is sent through ioctl from the application to the driver.
|
||||||
|
* To create a new effect application should set its @id to -1; the kernel
|
||||||
|
* will return assigned @id which can later be used to update or delete
|
||||||
|
* this effect.
|
||||||
|
*
|
||||||
|
* Direction of the effect is encoded as follows:
|
||||||
|
* 0 deg -> 0x0000 (down)
|
||||||
|
* 90 deg -> 0x4000 (left)
|
||||||
|
* 180 deg -> 0x8000 (up)
|
||||||
|
* 270 deg -> 0xC000 (right)
|
||||||
|
*/
|
||||||
|
struct ff_effect {
|
||||||
|
uint16_t type;
|
||||||
|
int16_t id;
|
||||||
|
uint16_t direction;
|
||||||
|
struct ff_trigger trigger;
|
||||||
|
struct ff_replay replay;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct ff_constant_effect constant;
|
||||||
|
struct ff_ramp_effect ramp;
|
||||||
|
struct ff_periodic_effect periodic;
|
||||||
|
struct ff_condition_effect condition[2]; /* One for each axis */
|
||||||
|
struct ff_rumble_effect rumble;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force feedback effect types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_RUMBLE 0x50
|
||||||
|
#define FF_PERIODIC 0x51
|
||||||
|
#define FF_CONSTANT 0x52
|
||||||
|
#define FF_SPRING 0x53
|
||||||
|
#define FF_FRICTION 0x54
|
||||||
|
#define FF_DAMPER 0x55
|
||||||
|
#define FF_INERTIA 0x56
|
||||||
|
#define FF_RAMP 0x57
|
||||||
|
|
||||||
|
#define FF_EFFECT_MIN FF_RUMBLE
|
||||||
|
#define FF_EFFECT_MAX FF_RAMP
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force feedback periodic effect types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_SQUARE 0x58
|
||||||
|
#define FF_TRIANGLE 0x59
|
||||||
|
#define FF_SINE 0x5a
|
||||||
|
#define FF_SAW_UP 0x5b
|
||||||
|
#define FF_SAW_DOWN 0x5c
|
||||||
|
#define FF_CUSTOM 0x5d
|
||||||
|
|
||||||
|
#define FF_WAVEFORM_MIN FF_SQUARE
|
||||||
|
#define FF_WAVEFORM_MAX FF_CUSTOM
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set ff device properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_GAIN 0x60
|
||||||
|
#define FF_AUTOCENTER 0x61
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ff->playback(effect_id = FF_GAIN) is the first effect_id to
|
||||||
|
* cause a collision with another ff method, in this case ff->set_gain().
|
||||||
|
* Therefore the greatest safe value for effect_id is FF_GAIN - 1,
|
||||||
|
* and thus the total number of effects should never exceed FF_GAIN.
|
||||||
|
*/
|
||||||
|
#define FF_MAX_EFFECTS FF_GAIN
|
||||||
|
|
||||||
|
#define FF_MAX 0x7f
|
||||||
|
#define FF_CNT (FF_MAX+1)
|
||||||
|
|
||||||
|
#endif /* _UAPI_INPUT_H */
|
||||||
232
include/linux/freebsd/uinput.h
Normal file
232
include/linux/freebsd/uinput.h
Normal file
|
|
@ -0,0 +1,232 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* User level driver support for input subsystem
|
||||||
|
*
|
||||||
|
* Heavily based on evdev.c by Vojtech Pavlik
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
|
||||||
|
*
|
||||||
|
* Changes/Revisions:
|
||||||
|
* 0.5 08/13/2015 (David Herrmann <dh.herrmann@gmail.com> &
|
||||||
|
* Benjamin Tissoires <benjamin.tissoires@redhat.com>)
|
||||||
|
* - add UI_DEV_SETUP ioctl
|
||||||
|
* - add UI_ABS_SETUP ioctl
|
||||||
|
* - add UI_GET_VERSION ioctl
|
||||||
|
* 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
|
||||||
|
* - add UI_GET_SYSNAME ioctl
|
||||||
|
* 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
|
||||||
|
* - update ff support for the changes in kernel interface
|
||||||
|
* - add UINPUT_VERSION
|
||||||
|
* 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
|
||||||
|
* - added force feedback support
|
||||||
|
* - added UI_SET_PHYS
|
||||||
|
* 0.1 20/06/2002
|
||||||
|
* - first public version
|
||||||
|
*/
|
||||||
|
#ifndef _UAPI__UINPUT_H_
|
||||||
|
#define _UAPI__UINPUT_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
#define UINPUT_VERSION 5
|
||||||
|
#define UINPUT_MAX_NAME_SIZE 80
|
||||||
|
|
||||||
|
struct uinput_ff_upload {
|
||||||
|
uint32_t request_id;
|
||||||
|
int32_t retval;
|
||||||
|
struct ff_effect effect;
|
||||||
|
struct ff_effect old;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uinput_ff_erase {
|
||||||
|
uint32_t request_id;
|
||||||
|
int32_t retval;
|
||||||
|
uint32_t effect_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ioctl */
|
||||||
|
#define UINPUT_IOCTL_BASE 'U'
|
||||||
|
#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
|
||||||
|
#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
|
||||||
|
|
||||||
|
struct uinput_setup {
|
||||||
|
struct input_id id;
|
||||||
|
char name[UINPUT_MAX_NAME_SIZE];
|
||||||
|
uint32_t ff_effects_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_DEV_SETUP - Set device parameters for setup
|
||||||
|
*
|
||||||
|
* This ioctl sets parameters for the input device to be created. It
|
||||||
|
* supersedes the old "struct uinput_user_dev" method, which wrote this data
|
||||||
|
* via write(). To actually set the absolute axes UI_ABS_SETUP should be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* The ioctl takes a "struct uinput_setup" object as argument. The fields of
|
||||||
|
* this object are as follows:
|
||||||
|
* id: See the description of "struct input_id". This field is
|
||||||
|
* copied unchanged into the new device.
|
||||||
|
* name: This is used unchanged as name for the new device.
|
||||||
|
* ff_effects_max: This limits the maximum numbers of force-feedback effects.
|
||||||
|
* See below for a description of FF with uinput.
|
||||||
|
*
|
||||||
|
* This ioctl can be called multiple times and will overwrite previous values.
|
||||||
|
* If this ioctl fails with -EINVAL, it is recommended to use the old
|
||||||
|
* "uinput_user_dev" method via write() as a fallback, in case you run on an
|
||||||
|
* old kernel that does not support this ioctl.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with -EINVAL if it is not supported or if you passed
|
||||||
|
* incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
|
||||||
|
* passed uinput_setup object cannot be read/written.
|
||||||
|
* If this call fails, partial data may have already been applied to the
|
||||||
|
* internal device.
|
||||||
|
*/
|
||||||
|
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
|
||||||
|
|
||||||
|
struct uinput_abs_setup {
|
||||||
|
uint16_t code; /* axis code */
|
||||||
|
/* uint16_t filler; */
|
||||||
|
struct input_absinfo absinfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_ABS_SETUP - Set absolute axis information for the device to setup
|
||||||
|
*
|
||||||
|
* This ioctl sets one absolute axis information for the input device to be
|
||||||
|
* created. It supersedes the old "struct uinput_user_dev" method, which wrote
|
||||||
|
* part of this data and the content of UI_DEV_SETUP via write().
|
||||||
|
*
|
||||||
|
* The ioctl takes a "struct uinput_abs_setup" object as argument. The fields
|
||||||
|
* of this object are as follows:
|
||||||
|
* code: The corresponding input code associated with this axis
|
||||||
|
* (ABS_X, ABS_Y, etc...)
|
||||||
|
* absinfo: See "struct input_absinfo" for a description of this field.
|
||||||
|
* This field is copied unchanged into the kernel for the
|
||||||
|
* specified axis. If the axis is not enabled via
|
||||||
|
* UI_SET_ABSBIT, this ioctl will enable it.
|
||||||
|
*
|
||||||
|
* This ioctl can be called multiple times and will overwrite previous values.
|
||||||
|
* If this ioctl fails with -EINVAL, it is recommended to use the old
|
||||||
|
* "uinput_user_dev" method via write() as a fallback, in case you run on an
|
||||||
|
* old kernel that does not support this ioctl.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with -EINVAL if it is not supported or if you passed
|
||||||
|
* incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
|
||||||
|
* passed uinput_setup object cannot be read/written.
|
||||||
|
* If this call fails, partial data may have already been applied to the
|
||||||
|
* internal device.
|
||||||
|
*/
|
||||||
|
#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
|
||||||
|
|
||||||
|
#define UI_SET_EVBIT _IOWINT(UINPUT_IOCTL_BASE, 100)
|
||||||
|
#define UI_SET_KEYBIT _IOWINT(UINPUT_IOCTL_BASE, 101)
|
||||||
|
#define UI_SET_RELBIT _IOWINT(UINPUT_IOCTL_BASE, 102)
|
||||||
|
#define UI_SET_ABSBIT _IOWINT(UINPUT_IOCTL_BASE, 103)
|
||||||
|
#define UI_SET_MSCBIT _IOWINT(UINPUT_IOCTL_BASE, 104)
|
||||||
|
#define UI_SET_LEDBIT _IOWINT(UINPUT_IOCTL_BASE, 105)
|
||||||
|
#define UI_SET_SNDBIT _IOWINT(UINPUT_IOCTL_BASE, 106)
|
||||||
|
#define UI_SET_FFBIT _IOWINT(UINPUT_IOCTL_BASE, 107)
|
||||||
|
#define UI_SET_PHYS _IO(UINPUT_IOCTL_BASE, 108)
|
||||||
|
#define UI_SET_SWBIT _IOWINT(UINPUT_IOCTL_BASE, 109)
|
||||||
|
#define UI_SET_PROPBIT _IOWINT(UINPUT_IOCTL_BASE, 110)
|
||||||
|
|
||||||
|
#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
|
||||||
|
#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
|
||||||
|
#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
|
||||||
|
#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_GET_SYSNAME - get the sysfs name of the created uinput device
|
||||||
|
*
|
||||||
|
* @return the sysfs name of the created virtual input device.
|
||||||
|
* The complete sysfs path is then /sys/devices/virtual/input/--NAME--
|
||||||
|
* Usually, it is in the form "inputN"
|
||||||
|
*/
|
||||||
|
#define UI_GET_SYSNAME(len) _IOC(IOC_OUT, UINPUT_IOCTL_BASE, 44, len)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_GET_VERSION - Return version of uinput protocol
|
||||||
|
*
|
||||||
|
* This writes uinput protocol version implemented by the kernel into
|
||||||
|
* the integer pointed to by the ioctl argument. The protocol version
|
||||||
|
* is hard-coded in the kernel and is independent of the uinput device.
|
||||||
|
*/
|
||||||
|
#define UI_GET_VERSION _IOR(UINPUT_IOCTL_BASE, 45, unsigned int)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To write a force-feedback-capable driver, the upload_effect
|
||||||
|
* and erase_effect callbacks in input_dev must be implemented.
|
||||||
|
* The uinput driver will generate a fake input event when one of
|
||||||
|
* these callbacks are invoked. The userspace code then uses
|
||||||
|
* ioctls to retrieve additional parameters and send the return code.
|
||||||
|
* The callback blocks until this return code is sent.
|
||||||
|
*
|
||||||
|
* The described callback mechanism is only used if ff_effects_max
|
||||||
|
* is set.
|
||||||
|
*
|
||||||
|
* To implement upload_effect():
|
||||||
|
* 1. Wait for an event with type == EV_UINPUT and code == UI_FF_UPLOAD.
|
||||||
|
* A request ID will be given in 'value'.
|
||||||
|
* 2. Allocate a uinput_ff_upload struct, fill in request_id with
|
||||||
|
* the 'value' from the EV_UINPUT event.
|
||||||
|
* 3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the
|
||||||
|
* uinput_ff_upload struct. It will be filled in with the
|
||||||
|
* ff_effects passed to upload_effect().
|
||||||
|
* 4. Perform the effect upload, and place a return code back into
|
||||||
|
the uinput_ff_upload struct.
|
||||||
|
* 5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the
|
||||||
|
* uinput_ff_upload_effect struct. This will complete execution
|
||||||
|
* of our upload_effect() handler.
|
||||||
|
*
|
||||||
|
* To implement erase_effect():
|
||||||
|
* 1. Wait for an event with type == EV_UINPUT and code == UI_FF_ERASE.
|
||||||
|
* A request ID will be given in 'value'.
|
||||||
|
* 2. Allocate a uinput_ff_erase struct, fill in request_id with
|
||||||
|
* the 'value' from the EV_UINPUT event.
|
||||||
|
* 3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the
|
||||||
|
* uinput_ff_erase struct. It will be filled in with the
|
||||||
|
* effect ID passed to erase_effect().
|
||||||
|
* 4. Perform the effect erasure, and place a return code back
|
||||||
|
* into the uinput_ff_erase struct.
|
||||||
|
* 5. Issue a UI_END_FF_ERASE ioctl, also giving it the
|
||||||
|
* uinput_ff_erase_effect struct. This will complete execution
|
||||||
|
* of our erase_effect() handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the new event type, used only by uinput.
|
||||||
|
* 'code' is UI_FF_UPLOAD or UI_FF_ERASE, and 'value'
|
||||||
|
* is the unique request ID. This number was picked
|
||||||
|
* arbitrarily, above EV_MAX (since the input system
|
||||||
|
* never sees it) but in the range of a 16-bit int.
|
||||||
|
*/
|
||||||
|
#define EV_UINPUT 0x0101
|
||||||
|
#define UI_FF_UPLOAD 1
|
||||||
|
#define UI_FF_ERASE 2
|
||||||
|
|
||||||
|
struct uinput_user_dev {
|
||||||
|
char name[UINPUT_MAX_NAME_SIZE];
|
||||||
|
struct input_id id;
|
||||||
|
uint32_t ff_effects_max;
|
||||||
|
int32_t absmax[ABS_CNT];
|
||||||
|
int32_t absmin[ABS_CNT];
|
||||||
|
int32_t absfuzz[ABS_CNT];
|
||||||
|
int32_t absflat[ABS_CNT];
|
||||||
|
};
|
||||||
|
#endif /* _UAPI__UINPUT_H_ */
|
||||||
|
|
@ -1,486 +1,5 @@
|
||||||
/*
|
#ifdef __linux__
|
||||||
* Copyright (c) 1999-2002 Vojtech Pavlik
|
#include "linux/input.h"
|
||||||
*
|
#elif __FreeBSD__
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
#include "freebsd/input.h"
|
||||||
* under the terms of the GNU General Public License version 2 as published by
|
#endif
|
||||||
* the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
#ifndef _INPUT_H
|
|
||||||
#define _INPUT_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <linux/types.h>
|
|
||||||
|
|
||||||
#include "input-event-codes.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The event structure itself
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct input_event {
|
|
||||||
struct timeval time;
|
|
||||||
__u16 type;
|
|
||||||
__u16 code;
|
|
||||||
__s32 value;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Protocol version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define EV_VERSION 0x010001
|
|
||||||
|
|
||||||
/*
|
|
||||||
* IOCTLs (0x00 - 0x7f)
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct input_id {
|
|
||||||
__u16 bustype;
|
|
||||||
__u16 vendor;
|
|
||||||
__u16 product;
|
|
||||||
__u16 version;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls
|
|
||||||
* @value: latest reported value for the axis.
|
|
||||||
* @minimum: specifies minimum value for the axis.
|
|
||||||
* @maximum: specifies maximum value for the axis.
|
|
||||||
* @fuzz: specifies fuzz value that is used to filter noise from
|
|
||||||
* the event stream.
|
|
||||||
* @flat: values that are within this value will be discarded by
|
|
||||||
* joydev interface and reported as 0 instead.
|
|
||||||
* @resolution: specifies resolution for the values reported for
|
|
||||||
* the axis.
|
|
||||||
*
|
|
||||||
* Note that input core does not clamp reported values to the
|
|
||||||
* [minimum, maximum] limits, such task is left to userspace.
|
|
||||||
*
|
|
||||||
* Resolution for main axes (ABS_X, ABS_Y, ABS_Z) is reported in
|
|
||||||
* units per millimeter (units/mm), resolution for rotational axes
|
|
||||||
* (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian.
|
|
||||||
*/
|
|
||||||
struct input_absinfo {
|
|
||||||
__s32 value;
|
|
||||||
__s32 minimum;
|
|
||||||
__s32 maximum;
|
|
||||||
__s32 fuzz;
|
|
||||||
__s32 flat;
|
|
||||||
__s32 resolution;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
|
|
||||||
* @scancode: scancode represented in machine-endian form.
|
|
||||||
* @len: length of the scancode that resides in @scancode buffer.
|
|
||||||
* @index: index in the keymap, may be used instead of scancode
|
|
||||||
* @flags: allows to specify how kernel should handle the request. For
|
|
||||||
* example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
|
|
||||||
* should perform lookup in keymap by @index instead of @scancode
|
|
||||||
* @keycode: key code assigned to this scancode
|
|
||||||
*
|
|
||||||
* The structure is used to retrieve and modify keymap data. Users have
|
|
||||||
* option of performing lookup either by @scancode itself or by @index
|
|
||||||
* in keymap entry. EVIOCGKEYCODE will also return scancode or index
|
|
||||||
* (depending on which element was used to perform lookup).
|
|
||||||
*/
|
|
||||||
struct input_keymap_entry {
|
|
||||||
#define INPUT_KEYMAP_BY_INDEX (1 << 0)
|
|
||||||
__u8 flags;
|
|
||||||
__u8 len;
|
|
||||||
__u16 index;
|
|
||||||
__u32 keycode;
|
|
||||||
__u8 scancode[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct input_mask {
|
|
||||||
__u32 type;
|
|
||||||
__u32 codes_size;
|
|
||||||
__u64 codes_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
|
|
||||||
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
|
|
||||||
#define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */
|
|
||||||
#define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */
|
|
||||||
|
|
||||||
#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */
|
|
||||||
#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry)
|
|
||||||
#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */
|
|
||||||
#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry)
|
|
||||||
|
|
||||||
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */
|
|
||||||
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
|
|
||||||
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
|
|
||||||
#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) /* get device properties */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EVIOCGMTSLOTS(len) - get MT slot values
|
|
||||||
* @len: size of the data buffer in bytes
|
|
||||||
*
|
|
||||||
* The ioctl buffer argument should be binary equivalent to
|
|
||||||
*
|
|
||||||
* struct input_mt_request_layout {
|
|
||||||
* __u32 code;
|
|
||||||
* __s32 values[num_slots];
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* where num_slots is the (arbitrary) number of MT slots to extract.
|
|
||||||
*
|
|
||||||
* The ioctl size argument (len) is the size of the buffer, which
|
|
||||||
* should satisfy len = (num_slots + 1) * sizeof(__s32). If len is
|
|
||||||
* too small to fit all available slots, the first num_slots are
|
|
||||||
* returned.
|
|
||||||
*
|
|
||||||
* Before the call, code is set to the wanted ABS_MT event type. On
|
|
||||||
* return, values[] is filled with the slot values for the specified
|
|
||||||
* ABS_MT code.
|
|
||||||
*
|
|
||||||
* If the request code is not an ABS_MT value, -EINVAL is returned.
|
|
||||||
*/
|
|
||||||
#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
|
|
||||||
|
|
||||||
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */
|
|
||||||
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
|
|
||||||
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
|
|
||||||
#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */
|
|
||||||
|
|
||||||
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len) /* get event bits */
|
|
||||||
#define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo) /* get abs value/limits */
|
|
||||||
#define EVIOCSABS(abs) _IOW('E', 0xc0 + (abs), struct input_absinfo) /* set abs value/limits */
|
|
||||||
|
|
||||||
#define EVIOCSFF _IOW('E', 0x80, struct ff_effect) /* send a force effect to a force feedback device */
|
|
||||||
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
|
|
||||||
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
|
|
||||||
|
|
||||||
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
|
|
||||||
#define EVIOCREVOKE _IOW('E', 0x91, int) /* Revoke device access */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EVIOCGMASK - Retrieve current event mask
|
|
||||||
*
|
|
||||||
* This ioctl allows user to retrieve the current event mask for specific
|
|
||||||
* event type. The argument must be of type "struct input_mask" and
|
|
||||||
* specifies the event type to query, the address of the receive buffer and
|
|
||||||
* the size of the receive buffer.
|
|
||||||
*
|
|
||||||
* The event mask is a per-client mask that specifies which events are
|
|
||||||
* forwarded to the client. Each event code is represented by a single bit
|
|
||||||
* in the event mask. If the bit is set, the event is passed to the client
|
|
||||||
* normally. Otherwise, the event is filtered and will never be queued on
|
|
||||||
* the client's receive buffer.
|
|
||||||
*
|
|
||||||
* Event masks do not affect global state of the input device. They only
|
|
||||||
* affect the file descriptor they are applied to.
|
|
||||||
*
|
|
||||||
* The default event mask for a client has all bits set, i.e. all events
|
|
||||||
* are forwarded to the client. If the kernel is queried for an unknown
|
|
||||||
* event type or if the receive buffer is larger than the number of
|
|
||||||
* event codes known to the kernel, the kernel returns all zeroes for those
|
|
||||||
* codes.
|
|
||||||
*
|
|
||||||
* At maximum, codes_size bytes are copied.
|
|
||||||
*
|
|
||||||
* This ioctl may fail with ENODEV in case the file is revoked, EFAULT
|
|
||||||
* if the receive-buffer points to invalid memory, or EINVAL if the kernel
|
|
||||||
* does not implement the ioctl.
|
|
||||||
*/
|
|
||||||
#define EVIOCGMASK _IOR('E', 0x92, struct input_mask) /* Get event-masks */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EVIOCSMASK - Set event mask
|
|
||||||
*
|
|
||||||
* This ioctl is the counterpart to EVIOCGMASK. Instead of receiving the
|
|
||||||
* current event mask, this changes the client's event mask for a specific
|
|
||||||
* type. See EVIOCGMASK for a description of event-masks and the
|
|
||||||
* argument-type.
|
|
||||||
*
|
|
||||||
* This ioctl provides full forward compatibility. If the passed event type
|
|
||||||
* is unknown to the kernel, or if the number of event codes specified in
|
|
||||||
* the mask is bigger than what is known to the kernel, the ioctl is still
|
|
||||||
* accepted and applied. However, any unknown codes are left untouched and
|
|
||||||
* stay cleared. That means, the kernel always filters unknown codes
|
|
||||||
* regardless of what the client requests. If the new mask doesn't cover
|
|
||||||
* all known event-codes, all remaining codes are automatically cleared and
|
|
||||||
* thus filtered.
|
|
||||||
*
|
|
||||||
* This ioctl may fail with ENODEV in case the file is revoked. EFAULT is
|
|
||||||
* returned if the receive-buffer points to invalid memory. EINVAL is returned
|
|
||||||
* if the kernel does not implement the ioctl.
|
|
||||||
*/
|
|
||||||
#define EVIOCSMASK _IOW('E', 0x93, struct input_mask) /* Set event-masks */
|
|
||||||
|
|
||||||
#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* IDs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define ID_BUS 0
|
|
||||||
#define ID_VENDOR 1
|
|
||||||
#define ID_PRODUCT 2
|
|
||||||
#define ID_VERSION 3
|
|
||||||
|
|
||||||
#define BUS_PCI 0x01
|
|
||||||
#define BUS_ISAPNP 0x02
|
|
||||||
#define BUS_USB 0x03
|
|
||||||
#define BUS_HIL 0x04
|
|
||||||
#define BUS_BLUETOOTH 0x05
|
|
||||||
#define BUS_VIRTUAL 0x06
|
|
||||||
|
|
||||||
#define BUS_ISA 0x10
|
|
||||||
#define BUS_I8042 0x11
|
|
||||||
#define BUS_XTKBD 0x12
|
|
||||||
#define BUS_RS232 0x13
|
|
||||||
#define BUS_GAMEPORT 0x14
|
|
||||||
#define BUS_PARPORT 0x15
|
|
||||||
#define BUS_AMIGA 0x16
|
|
||||||
#define BUS_ADB 0x17
|
|
||||||
#define BUS_I2C 0x18
|
|
||||||
#define BUS_HOST 0x19
|
|
||||||
#define BUS_GSC 0x1A
|
|
||||||
#define BUS_ATARI 0x1B
|
|
||||||
#define BUS_SPI 0x1C
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MT_TOOL types
|
|
||||||
*/
|
|
||||||
#define MT_TOOL_FINGER 0
|
|
||||||
#define MT_TOOL_PEN 1
|
|
||||||
#define MT_TOOL_PALM 2
|
|
||||||
#define MT_TOOL_MAX 2
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Values describing the status of a force-feedback effect
|
|
||||||
*/
|
|
||||||
#define FF_STATUS_STOPPED 0x00
|
|
||||||
#define FF_STATUS_PLAYING 0x01
|
|
||||||
#define FF_STATUS_MAX 0x01
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structures used in ioctls to upload effects to a device
|
|
||||||
* They are pieces of a bigger structure (called ff_effect)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* All duration values are expressed in ms. Values above 32767 ms (0x7fff)
|
|
||||||
* should not be used and have unspecified results.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_replay - defines scheduling of the force-feedback effect
|
|
||||||
* @length: duration of the effect
|
|
||||||
* @delay: delay before effect should start playing
|
|
||||||
*/
|
|
||||||
struct ff_replay {
|
|
||||||
__u16 length;
|
|
||||||
__u16 delay;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_trigger - defines what triggers the force-feedback effect
|
|
||||||
* @button: number of the button triggering the effect
|
|
||||||
* @interval: controls how soon the effect can be re-triggered
|
|
||||||
*/
|
|
||||||
struct ff_trigger {
|
|
||||||
__u16 button;
|
|
||||||
__u16 interval;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_envelope - generic force-feedback effect envelope
|
|
||||||
* @attack_length: duration of the attack (ms)
|
|
||||||
* @attack_level: level at the beginning of the attack
|
|
||||||
* @fade_length: duration of fade (ms)
|
|
||||||
* @fade_level: level at the end of fade
|
|
||||||
*
|
|
||||||
* The @attack_level and @fade_level are absolute values; when applying
|
|
||||||
* envelope force-feedback core will convert to positive/negative
|
|
||||||
* value based on polarity of the default level of the effect.
|
|
||||||
* Valid range for the attack and fade levels is 0x0000 - 0x7fff
|
|
||||||
*/
|
|
||||||
struct ff_envelope {
|
|
||||||
__u16 attack_length;
|
|
||||||
__u16 attack_level;
|
|
||||||
__u16 fade_length;
|
|
||||||
__u16 fade_level;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_constant_effect - defines parameters of a constant force-feedback effect
|
|
||||||
* @level: strength of the effect; may be negative
|
|
||||||
* @envelope: envelope data
|
|
||||||
*/
|
|
||||||
struct ff_constant_effect {
|
|
||||||
__s16 level;
|
|
||||||
struct ff_envelope envelope;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_ramp_effect - defines parameters of a ramp force-feedback effect
|
|
||||||
* @start_level: beginning strength of the effect; may be negative
|
|
||||||
* @end_level: final strength of the effect; may be negative
|
|
||||||
* @envelope: envelope data
|
|
||||||
*/
|
|
||||||
struct ff_ramp_effect {
|
|
||||||
__s16 start_level;
|
|
||||||
__s16 end_level;
|
|
||||||
struct ff_envelope envelope;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_condition_effect - defines a spring or friction force-feedback effect
|
|
||||||
* @right_saturation: maximum level when joystick moved all way to the right
|
|
||||||
* @left_saturation: same for the left side
|
|
||||||
* @right_coeff: controls how fast the force grows when the joystick moves
|
|
||||||
* to the right
|
|
||||||
* @left_coeff: same for the left side
|
|
||||||
* @deadband: size of the dead zone, where no force is produced
|
|
||||||
* @center: position of the dead zone
|
|
||||||
*/
|
|
||||||
struct ff_condition_effect {
|
|
||||||
__u16 right_saturation;
|
|
||||||
__u16 left_saturation;
|
|
||||||
|
|
||||||
__s16 right_coeff;
|
|
||||||
__s16 left_coeff;
|
|
||||||
|
|
||||||
__u16 deadband;
|
|
||||||
__s16 center;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_periodic_effect - defines parameters of a periodic force-feedback effect
|
|
||||||
* @waveform: kind of the effect (wave)
|
|
||||||
* @period: period of the wave (ms)
|
|
||||||
* @magnitude: peak value
|
|
||||||
* @offset: mean value of the wave (roughly)
|
|
||||||
* @phase: 'horizontal' shift
|
|
||||||
* @envelope: envelope data
|
|
||||||
* @custom_len: number of samples (FF_CUSTOM only)
|
|
||||||
* @custom_data: buffer of samples (FF_CUSTOM only)
|
|
||||||
*
|
|
||||||
* Known waveforms - FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP,
|
|
||||||
* FF_SAW_DOWN, FF_CUSTOM. The exact syntax FF_CUSTOM is undefined
|
|
||||||
* for the time being as no driver supports it yet.
|
|
||||||
*
|
|
||||||
* Note: the data pointed by custom_data is copied by the driver.
|
|
||||||
* You can therefore dispose of the memory after the upload/update.
|
|
||||||
*/
|
|
||||||
struct ff_periodic_effect {
|
|
||||||
__u16 waveform;
|
|
||||||
__u16 period;
|
|
||||||
__s16 magnitude;
|
|
||||||
__s16 offset;
|
|
||||||
__u16 phase;
|
|
||||||
|
|
||||||
struct ff_envelope envelope;
|
|
||||||
|
|
||||||
__u32 custom_len;
|
|
||||||
__s16 *custom_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
|
|
||||||
* @strong_magnitude: magnitude of the heavy motor
|
|
||||||
* @weak_magnitude: magnitude of the light one
|
|
||||||
*
|
|
||||||
* Some rumble pads have two motors of different weight. Strong_magnitude
|
|
||||||
* represents the magnitude of the vibration generated by the heavy one.
|
|
||||||
*/
|
|
||||||
struct ff_rumble_effect {
|
|
||||||
__u16 strong_magnitude;
|
|
||||||
__u16 weak_magnitude;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct ff_effect - defines force feedback effect
|
|
||||||
* @type: type of the effect (FF_CONSTANT, FF_PERIODIC, FF_RAMP, FF_SPRING,
|
|
||||||
* FF_FRICTION, FF_DAMPER, FF_RUMBLE, FF_INERTIA, or FF_CUSTOM)
|
|
||||||
* @id: an unique id assigned to an effect
|
|
||||||
* @direction: direction of the effect
|
|
||||||
* @trigger: trigger conditions (struct ff_trigger)
|
|
||||||
* @replay: scheduling of the effect (struct ff_replay)
|
|
||||||
* @u: effect-specific structure (one of ff_constant_effect, ff_ramp_effect,
|
|
||||||
* ff_periodic_effect, ff_condition_effect, ff_rumble_effect) further
|
|
||||||
* defining effect parameters
|
|
||||||
*
|
|
||||||
* This structure is sent through ioctl from the application to the driver.
|
|
||||||
* To create a new effect application should set its @id to -1; the kernel
|
|
||||||
* will return assigned @id which can later be used to update or delete
|
|
||||||
* this effect.
|
|
||||||
*
|
|
||||||
* Direction of the effect is encoded as follows:
|
|
||||||
* 0 deg -> 0x0000 (down)
|
|
||||||
* 90 deg -> 0x4000 (left)
|
|
||||||
* 180 deg -> 0x8000 (up)
|
|
||||||
* 270 deg -> 0xC000 (right)
|
|
||||||
*/
|
|
||||||
struct ff_effect {
|
|
||||||
__u16 type;
|
|
||||||
__s16 id;
|
|
||||||
__u16 direction;
|
|
||||||
struct ff_trigger trigger;
|
|
||||||
struct ff_replay replay;
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct ff_constant_effect constant;
|
|
||||||
struct ff_ramp_effect ramp;
|
|
||||||
struct ff_periodic_effect periodic;
|
|
||||||
struct ff_condition_effect condition[2]; /* One for each axis */
|
|
||||||
struct ff_rumble_effect rumble;
|
|
||||||
} u;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Force feedback effect types
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FF_RUMBLE 0x50
|
|
||||||
#define FF_PERIODIC 0x51
|
|
||||||
#define FF_CONSTANT 0x52
|
|
||||||
#define FF_SPRING 0x53
|
|
||||||
#define FF_FRICTION 0x54
|
|
||||||
#define FF_DAMPER 0x55
|
|
||||||
#define FF_INERTIA 0x56
|
|
||||||
#define FF_RAMP 0x57
|
|
||||||
|
|
||||||
#define FF_EFFECT_MIN FF_RUMBLE
|
|
||||||
#define FF_EFFECT_MAX FF_RAMP
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Force feedback periodic effect types
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FF_SQUARE 0x58
|
|
||||||
#define FF_TRIANGLE 0x59
|
|
||||||
#define FF_SINE 0x5a
|
|
||||||
#define FF_SAW_UP 0x5b
|
|
||||||
#define FF_SAW_DOWN 0x5c
|
|
||||||
#define FF_CUSTOM 0x5d
|
|
||||||
|
|
||||||
#define FF_WAVEFORM_MIN FF_SQUARE
|
|
||||||
#define FF_WAVEFORM_MAX FF_CUSTOM
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set ff device properties
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FF_GAIN 0x60
|
|
||||||
#define FF_AUTOCENTER 0x61
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ff->playback(effect_id = FF_GAIN) is the first effect_id to
|
|
||||||
* cause a collision with another ff method, in this case ff->set_gain().
|
|
||||||
* Therefore the greatest safe value for effect_id is FF_GAIN - 1,
|
|
||||||
* and thus the total number of effects should never exceed FF_GAIN.
|
|
||||||
*/
|
|
||||||
#define FF_MAX_EFFECTS FF_GAIN
|
|
||||||
|
|
||||||
#define FF_MAX 0x7f
|
|
||||||
#define FF_CNT (FF_MAX+1)
|
|
||||||
|
|
||||||
#endif /* _INPUT_H */
|
|
||||||
|
|
|
||||||
1003
include/linux/linux/input-event-codes.h
Normal file
1003
include/linux/linux/input-event-codes.h
Normal file
File diff suppressed because it is too large
Load diff
539
include/linux/linux/input.h
Normal file
539
include/linux/linux/input.h
Normal file
|
|
@ -0,0 +1,539 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1999-2002 Vojtech Pavlik
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef _UAPI_INPUT_H
|
||||||
|
#define _UAPI_INPUT_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __KERNEL__
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "input-event-codes.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The event structure itself
|
||||||
|
* Note that __USE_TIME_BITS64 is defined by libc based on
|
||||||
|
* application's request to use 64 bit time_t.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct input_event {
|
||||||
|
#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__)
|
||||||
|
struct timeval time;
|
||||||
|
#define input_event_sec time.tv_sec
|
||||||
|
#define input_event_usec time.tv_usec
|
||||||
|
#else
|
||||||
|
__kernel_ulong_t __sec;
|
||||||
|
#if defined(__sparc__) && defined(__arch64__)
|
||||||
|
unsigned int __usec;
|
||||||
|
unsigned int __pad;
|
||||||
|
#else
|
||||||
|
__kernel_ulong_t __usec;
|
||||||
|
#endif
|
||||||
|
#define input_event_sec __sec
|
||||||
|
#define input_event_usec __usec
|
||||||
|
#endif
|
||||||
|
__u16 type;
|
||||||
|
__u16 code;
|
||||||
|
__s32 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protocol version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EV_VERSION 0x010001
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IOCTLs (0x00 - 0x7f)
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct input_id {
|
||||||
|
__u16 bustype;
|
||||||
|
__u16 vendor;
|
||||||
|
__u16 product;
|
||||||
|
__u16 version;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct input_absinfo - used by EVIOCGABS/EVIOCSABS ioctls
|
||||||
|
* @value: latest reported value for the axis.
|
||||||
|
* @minimum: specifies minimum value for the axis.
|
||||||
|
* @maximum: specifies maximum value for the axis.
|
||||||
|
* @fuzz: specifies fuzz value that is used to filter noise from
|
||||||
|
* the event stream.
|
||||||
|
* @flat: values that are within this value will be discarded by
|
||||||
|
* joydev interface and reported as 0 instead.
|
||||||
|
* @resolution: specifies resolution for the values reported for
|
||||||
|
* the axis.
|
||||||
|
*
|
||||||
|
* Note that input core does not clamp reported values to the
|
||||||
|
* [minimum, maximum] limits, such task is left to userspace.
|
||||||
|
*
|
||||||
|
* The default resolution for main axes (ABS_X, ABS_Y, ABS_Z,
|
||||||
|
* ABS_MT_POSITION_X, ABS_MT_POSITION_Y) is reported in units
|
||||||
|
* per millimeter (units/mm), resolution for rotational axes
|
||||||
|
* (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian.
|
||||||
|
* The resolution for the size axes (ABS_MT_TOUCH_MAJOR,
|
||||||
|
* ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MAJOR, ABS_MT_WIDTH_MINOR)
|
||||||
|
* is reported in units per millimeter (units/mm).
|
||||||
|
* When INPUT_PROP_ACCELEROMETER is set the resolution changes.
|
||||||
|
* The main axes (ABS_X, ABS_Y, ABS_Z) are then reported in
|
||||||
|
* units per g (units/g) and in units per degree per second
|
||||||
|
* (units/deg/s) for rotational axes (ABS_RX, ABS_RY, ABS_RZ).
|
||||||
|
*/
|
||||||
|
struct input_absinfo {
|
||||||
|
__s32 value;
|
||||||
|
__s32 minimum;
|
||||||
|
__s32 maximum;
|
||||||
|
__s32 fuzz;
|
||||||
|
__s32 flat;
|
||||||
|
__s32 resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
|
||||||
|
* @scancode: scancode represented in machine-endian form.
|
||||||
|
* @len: length of the scancode that resides in @scancode buffer.
|
||||||
|
* @index: index in the keymap, may be used instead of scancode
|
||||||
|
* @flags: allows to specify how kernel should handle the request. For
|
||||||
|
* example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
|
||||||
|
* should perform lookup in keymap by @index instead of @scancode
|
||||||
|
* @keycode: key code assigned to this scancode
|
||||||
|
*
|
||||||
|
* The structure is used to retrieve and modify keymap data. Users have
|
||||||
|
* option of performing lookup either by @scancode itself or by @index
|
||||||
|
* in keymap entry. EVIOCGKEYCODE will also return scancode or index
|
||||||
|
* (depending on which element was used to perform lookup).
|
||||||
|
*/
|
||||||
|
struct input_keymap_entry {
|
||||||
|
#define INPUT_KEYMAP_BY_INDEX (1 << 0)
|
||||||
|
__u8 flags;
|
||||||
|
__u8 len;
|
||||||
|
__u16 index;
|
||||||
|
__u32 keycode;
|
||||||
|
__u8 scancode[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct input_mask {
|
||||||
|
__u32 type;
|
||||||
|
__u32 codes_size;
|
||||||
|
__u64 codes_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
|
||||||
|
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
|
||||||
|
#define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */
|
||||||
|
#define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */
|
||||||
|
|
||||||
|
#define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */
|
||||||
|
#define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry)
|
||||||
|
#define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */
|
||||||
|
#define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry)
|
||||||
|
|
||||||
|
#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */
|
||||||
|
#define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */
|
||||||
|
#define EVIOCGUNIQ(len) _IOC(_IOC_READ, 'E', 0x08, len) /* get unique identifier */
|
||||||
|
#define EVIOCGPROP(len) _IOC(_IOC_READ, 'E', 0x09, len) /* get device properties */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVIOCGMTSLOTS(len) - get MT slot values
|
||||||
|
* @len: size of the data buffer in bytes
|
||||||
|
*
|
||||||
|
* The ioctl buffer argument should be binary equivalent to
|
||||||
|
*
|
||||||
|
* struct input_mt_request_layout {
|
||||||
|
* __u32 code;
|
||||||
|
* __s32 values[num_slots];
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* where num_slots is the (arbitrary) number of MT slots to extract.
|
||||||
|
*
|
||||||
|
* The ioctl size argument (len) is the size of the buffer, which
|
||||||
|
* should satisfy len = (num_slots + 1) * sizeof(__s32). If len is
|
||||||
|
* too small to fit all available slots, the first num_slots are
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* Before the call, code is set to the wanted ABS_MT event type. On
|
||||||
|
* return, values[] is filled with the slot values for the specified
|
||||||
|
* ABS_MT code.
|
||||||
|
*
|
||||||
|
* If the request code is not an ABS_MT value, -EINVAL is returned.
|
||||||
|
*/
|
||||||
|
#define EVIOCGMTSLOTS(len) _IOC(_IOC_READ, 'E', 0x0a, len)
|
||||||
|
|
||||||
|
#define EVIOCGKEY(len) _IOC(_IOC_READ, 'E', 0x18, len) /* get global key state */
|
||||||
|
#define EVIOCGLED(len) _IOC(_IOC_READ, 'E', 0x19, len) /* get all LEDs */
|
||||||
|
#define EVIOCGSND(len) _IOC(_IOC_READ, 'E', 0x1a, len) /* get all sounds status */
|
||||||
|
#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */
|
||||||
|
|
||||||
|
#define EVIOCGBIT(ev,len) _IOC(_IOC_READ, 'E', 0x20 + (ev), len) /* get event bits */
|
||||||
|
#define EVIOCGABS(abs) _IOR('E', 0x40 + (abs), struct input_absinfo) /* get abs value/limits */
|
||||||
|
#define EVIOCSABS(abs) _IOW('E', 0xc0 + (abs), struct input_absinfo) /* set abs value/limits */
|
||||||
|
|
||||||
|
#define EVIOCSFF _IOW('E', 0x80, struct ff_effect) /* send a force effect to a force feedback device */
|
||||||
|
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
|
||||||
|
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
|
||||||
|
|
||||||
|
#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */
|
||||||
|
#define EVIOCREVOKE _IOW('E', 0x91, int) /* Revoke device access */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVIOCGMASK - Retrieve current event mask
|
||||||
|
*
|
||||||
|
* This ioctl allows user to retrieve the current event mask for specific
|
||||||
|
* event type. The argument must be of type "struct input_mask" and
|
||||||
|
* specifies the event type to query, the address of the receive buffer and
|
||||||
|
* the size of the receive buffer.
|
||||||
|
*
|
||||||
|
* The event mask is a per-client mask that specifies which events are
|
||||||
|
* forwarded to the client. Each event code is represented by a single bit
|
||||||
|
* in the event mask. If the bit is set, the event is passed to the client
|
||||||
|
* normally. Otherwise, the event is filtered and will never be queued on
|
||||||
|
* the client's receive buffer.
|
||||||
|
*
|
||||||
|
* Event masks do not affect global state of the input device. They only
|
||||||
|
* affect the file descriptor they are applied to.
|
||||||
|
*
|
||||||
|
* The default event mask for a client has all bits set, i.e. all events
|
||||||
|
* are forwarded to the client. If the kernel is queried for an unknown
|
||||||
|
* event type or if the receive buffer is larger than the number of
|
||||||
|
* event codes known to the kernel, the kernel returns all zeroes for those
|
||||||
|
* codes.
|
||||||
|
*
|
||||||
|
* At maximum, codes_size bytes are copied.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with ENODEV in case the file is revoked, EFAULT
|
||||||
|
* if the receive-buffer points to invalid memory, or EINVAL if the kernel
|
||||||
|
* does not implement the ioctl.
|
||||||
|
*/
|
||||||
|
#define EVIOCGMASK _IOR('E', 0x92, struct input_mask) /* Get event-masks */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EVIOCSMASK - Set event mask
|
||||||
|
*
|
||||||
|
* This ioctl is the counterpart to EVIOCGMASK. Instead of receiving the
|
||||||
|
* current event mask, this changes the client's event mask for a specific
|
||||||
|
* type. See EVIOCGMASK for a description of event-masks and the
|
||||||
|
* argument-type.
|
||||||
|
*
|
||||||
|
* This ioctl provides full forward compatibility. If the passed event type
|
||||||
|
* is unknown to the kernel, or if the number of event codes specified in
|
||||||
|
* the mask is bigger than what is known to the kernel, the ioctl is still
|
||||||
|
* accepted and applied. However, any unknown codes are left untouched and
|
||||||
|
* stay cleared. That means, the kernel always filters unknown codes
|
||||||
|
* regardless of what the client requests. If the new mask doesn't cover
|
||||||
|
* all known event-codes, all remaining codes are automatically cleared and
|
||||||
|
* thus filtered.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with ENODEV in case the file is revoked. EFAULT is
|
||||||
|
* returned if the receive-buffer points to invalid memory. EINVAL is returned
|
||||||
|
* if the kernel does not implement the ioctl.
|
||||||
|
*/
|
||||||
|
#define EVIOCSMASK _IOW('E', 0x93, struct input_mask) /* Set event-masks */
|
||||||
|
|
||||||
|
#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IDs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ID_BUS 0
|
||||||
|
#define ID_VENDOR 1
|
||||||
|
#define ID_PRODUCT 2
|
||||||
|
#define ID_VERSION 3
|
||||||
|
|
||||||
|
#define BUS_PCI 0x01
|
||||||
|
#define BUS_ISAPNP 0x02
|
||||||
|
#define BUS_USB 0x03
|
||||||
|
#define BUS_HIL 0x04
|
||||||
|
#define BUS_BLUETOOTH 0x05
|
||||||
|
#define BUS_VIRTUAL 0x06
|
||||||
|
|
||||||
|
#define BUS_ISA 0x10
|
||||||
|
#define BUS_I8042 0x11
|
||||||
|
#define BUS_XTKBD 0x12
|
||||||
|
#define BUS_RS232 0x13
|
||||||
|
#define BUS_GAMEPORT 0x14
|
||||||
|
#define BUS_PARPORT 0x15
|
||||||
|
#define BUS_AMIGA 0x16
|
||||||
|
#define BUS_ADB 0x17
|
||||||
|
#define BUS_I2C 0x18
|
||||||
|
#define BUS_HOST 0x19
|
||||||
|
#define BUS_GSC 0x1A
|
||||||
|
#define BUS_ATARI 0x1B
|
||||||
|
#define BUS_SPI 0x1C
|
||||||
|
#define BUS_RMI 0x1D
|
||||||
|
#define BUS_CEC 0x1E
|
||||||
|
#define BUS_INTEL_ISHTP 0x1F
|
||||||
|
#define BUS_AMD_SFH 0x20
|
||||||
|
#define BUS_SDW 0x21
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MT_TOOL types
|
||||||
|
*/
|
||||||
|
#define MT_TOOL_FINGER 0x00
|
||||||
|
#define MT_TOOL_PEN 0x01
|
||||||
|
#define MT_TOOL_PALM 0x02
|
||||||
|
#define MT_TOOL_DIAL 0x0a
|
||||||
|
#define MT_TOOL_MAX 0x0f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Values describing the status of a force-feedback effect
|
||||||
|
*/
|
||||||
|
#define FF_STATUS_STOPPED 0x00
|
||||||
|
#define FF_STATUS_PLAYING 0x01
|
||||||
|
#define FF_STATUS_MAX 0x01
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structures used in ioctls to upload effects to a device
|
||||||
|
* They are pieces of a bigger structure (called ff_effect)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All duration values are expressed in ms. Values above 32767 ms (0x7fff)
|
||||||
|
* should not be used and have unspecified results.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_replay - defines scheduling of the force-feedback effect
|
||||||
|
* @length: duration of the effect
|
||||||
|
* @delay: delay before effect should start playing
|
||||||
|
*/
|
||||||
|
struct ff_replay {
|
||||||
|
__u16 length;
|
||||||
|
__u16 delay;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_trigger - defines what triggers the force-feedback effect
|
||||||
|
* @button: number of the button triggering the effect
|
||||||
|
* @interval: controls how soon the effect can be re-triggered
|
||||||
|
*/
|
||||||
|
struct ff_trigger {
|
||||||
|
__u16 button;
|
||||||
|
__u16 interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_envelope - generic force-feedback effect envelope
|
||||||
|
* @attack_length: duration of the attack (ms)
|
||||||
|
* @attack_level: level at the beginning of the attack
|
||||||
|
* @fade_length: duration of fade (ms)
|
||||||
|
* @fade_level: level at the end of fade
|
||||||
|
*
|
||||||
|
* The @attack_level and @fade_level are absolute values; when applying
|
||||||
|
* envelope force-feedback core will convert to positive/negative
|
||||||
|
* value based on polarity of the default level of the effect.
|
||||||
|
* Valid range for the attack and fade levels is 0x0000 - 0x7fff
|
||||||
|
*/
|
||||||
|
struct ff_envelope {
|
||||||
|
__u16 attack_length;
|
||||||
|
__u16 attack_level;
|
||||||
|
__u16 fade_length;
|
||||||
|
__u16 fade_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_constant_effect - defines parameters of a constant force-feedback effect
|
||||||
|
* @level: strength of the effect; may be negative
|
||||||
|
* @envelope: envelope data
|
||||||
|
*/
|
||||||
|
struct ff_constant_effect {
|
||||||
|
__s16 level;
|
||||||
|
struct ff_envelope envelope;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_ramp_effect - defines parameters of a ramp force-feedback effect
|
||||||
|
* @start_level: beginning strength of the effect; may be negative
|
||||||
|
* @end_level: final strength of the effect; may be negative
|
||||||
|
* @envelope: envelope data
|
||||||
|
*/
|
||||||
|
struct ff_ramp_effect {
|
||||||
|
__s16 start_level;
|
||||||
|
__s16 end_level;
|
||||||
|
struct ff_envelope envelope;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_condition_effect - defines a spring or friction force-feedback effect
|
||||||
|
* @right_saturation: maximum level when joystick moved all way to the right
|
||||||
|
* @left_saturation: same for the left side
|
||||||
|
* @right_coeff: controls how fast the force grows when the joystick moves
|
||||||
|
* to the right
|
||||||
|
* @left_coeff: same for the left side
|
||||||
|
* @deadband: size of the dead zone, where no force is produced
|
||||||
|
* @center: position of the dead zone
|
||||||
|
*/
|
||||||
|
struct ff_condition_effect {
|
||||||
|
__u16 right_saturation;
|
||||||
|
__u16 left_saturation;
|
||||||
|
|
||||||
|
__s16 right_coeff;
|
||||||
|
__s16 left_coeff;
|
||||||
|
|
||||||
|
__u16 deadband;
|
||||||
|
__s16 center;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_periodic_effect - defines parameters of a periodic force-feedback effect
|
||||||
|
* @waveform: kind of the effect (wave)
|
||||||
|
* @period: period of the wave (ms)
|
||||||
|
* @magnitude: peak value
|
||||||
|
* @offset: mean value of the wave (roughly)
|
||||||
|
* @phase: 'horizontal' shift
|
||||||
|
* @envelope: envelope data
|
||||||
|
* @custom_len: number of samples (FF_CUSTOM only)
|
||||||
|
* @custom_data: buffer of samples (FF_CUSTOM only)
|
||||||
|
*
|
||||||
|
* Known waveforms - FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP,
|
||||||
|
* FF_SAW_DOWN, FF_CUSTOM. The exact syntax FF_CUSTOM is undefined
|
||||||
|
* for the time being as no driver supports it yet.
|
||||||
|
*
|
||||||
|
* Note: the data pointed by custom_data is copied by the driver.
|
||||||
|
* You can therefore dispose of the memory after the upload/update.
|
||||||
|
*/
|
||||||
|
struct ff_periodic_effect {
|
||||||
|
__u16 waveform;
|
||||||
|
__u16 period;
|
||||||
|
__s16 magnitude;
|
||||||
|
__s16 offset;
|
||||||
|
__u16 phase;
|
||||||
|
|
||||||
|
struct ff_envelope envelope;
|
||||||
|
|
||||||
|
__u32 custom_len;
|
||||||
|
__s16 *custom_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
|
||||||
|
* @strong_magnitude: magnitude of the heavy motor
|
||||||
|
* @weak_magnitude: magnitude of the light one
|
||||||
|
*
|
||||||
|
* Some rumble pads have two motors of different weight. Strong_magnitude
|
||||||
|
* represents the magnitude of the vibration generated by the heavy one.
|
||||||
|
*/
|
||||||
|
struct ff_rumble_effect {
|
||||||
|
__u16 strong_magnitude;
|
||||||
|
__u16 weak_magnitude;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_haptic_effect
|
||||||
|
* @hid_usage: hid_usage according to Haptics page (WAVEFORM_CLICK, etc.)
|
||||||
|
* @vendor_id: the waveform vendor ID if hid_usage is in the vendor-defined range
|
||||||
|
* @vendor_waveform_page: the vendor waveform page if hid_usage is in the vendor-defined range
|
||||||
|
* @intensity: strength of the effect as percentage
|
||||||
|
* @repeat_count: number of times to retrigger effect
|
||||||
|
* @retrigger_period: time before effect is retriggered (in ms)
|
||||||
|
*/
|
||||||
|
struct ff_haptic_effect {
|
||||||
|
__u16 hid_usage;
|
||||||
|
__u16 vendor_id;
|
||||||
|
__u8 vendor_waveform_page;
|
||||||
|
__u16 intensity;
|
||||||
|
__u16 repeat_count;
|
||||||
|
__u16 retrigger_period;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ff_effect - defines force feedback effect
|
||||||
|
* @type: type of the effect (FF_CONSTANT, FF_PERIODIC, FF_RAMP, FF_SPRING,
|
||||||
|
* FF_FRICTION, FF_DAMPER, FF_RUMBLE, FF_INERTIA, or FF_CUSTOM)
|
||||||
|
* @id: an unique id assigned to an effect
|
||||||
|
* @direction: direction of the effect
|
||||||
|
* @trigger: trigger conditions (struct ff_trigger)
|
||||||
|
* @replay: scheduling of the effect (struct ff_replay)
|
||||||
|
* @u: effect-specific structure (one of ff_constant_effect, ff_ramp_effect,
|
||||||
|
* ff_periodic_effect, ff_condition_effect, ff_rumble_effect) further
|
||||||
|
* defining effect parameters
|
||||||
|
*
|
||||||
|
* This structure is sent through ioctl from the application to the driver.
|
||||||
|
* To create a new effect application should set its @id to -1; the kernel
|
||||||
|
* will return assigned @id which can later be used to update or delete
|
||||||
|
* this effect.
|
||||||
|
*
|
||||||
|
* Direction of the effect is encoded as follows:
|
||||||
|
* 0 deg -> 0x0000 (down)
|
||||||
|
* 90 deg -> 0x4000 (left)
|
||||||
|
* 180 deg -> 0x8000 (up)
|
||||||
|
* 270 deg -> 0xC000 (right)
|
||||||
|
*/
|
||||||
|
struct ff_effect {
|
||||||
|
__u16 type;
|
||||||
|
__s16 id;
|
||||||
|
__u16 direction;
|
||||||
|
struct ff_trigger trigger;
|
||||||
|
struct ff_replay replay;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct ff_constant_effect constant;
|
||||||
|
struct ff_ramp_effect ramp;
|
||||||
|
struct ff_periodic_effect periodic;
|
||||||
|
struct ff_condition_effect condition[2]; /* One for each axis */
|
||||||
|
struct ff_rumble_effect rumble;
|
||||||
|
struct ff_haptic_effect haptic;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force feedback effect types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_HAPTIC 0x4f
|
||||||
|
#define FF_RUMBLE 0x50
|
||||||
|
#define FF_PERIODIC 0x51
|
||||||
|
#define FF_CONSTANT 0x52
|
||||||
|
#define FF_SPRING 0x53
|
||||||
|
#define FF_FRICTION 0x54
|
||||||
|
#define FF_DAMPER 0x55
|
||||||
|
#define FF_INERTIA 0x56
|
||||||
|
#define FF_RAMP 0x57
|
||||||
|
|
||||||
|
#define FF_EFFECT_MIN FF_HAPTIC
|
||||||
|
#define FF_EFFECT_MAX FF_RAMP
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force feedback periodic effect types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_SQUARE 0x58
|
||||||
|
#define FF_TRIANGLE 0x59
|
||||||
|
#define FF_SINE 0x5a
|
||||||
|
#define FF_SAW_UP 0x5b
|
||||||
|
#define FF_SAW_DOWN 0x5c
|
||||||
|
#define FF_CUSTOM 0x5d
|
||||||
|
|
||||||
|
#define FF_WAVEFORM_MIN FF_SQUARE
|
||||||
|
#define FF_WAVEFORM_MAX FF_CUSTOM
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set ff device properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_GAIN 0x60
|
||||||
|
#define FF_AUTOCENTER 0x61
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ff->playback(effect_id = FF_GAIN) is the first effect_id to
|
||||||
|
* cause a collision with another ff method, in this case ff->set_gain().
|
||||||
|
* Therefore the greatest safe value for effect_id is FF_GAIN - 1,
|
||||||
|
* and thus the total number of effects should never exceed FF_GAIN.
|
||||||
|
*/
|
||||||
|
#define FF_MAX_EFFECTS FF_GAIN
|
||||||
|
|
||||||
|
#define FF_MAX 0x7f
|
||||||
|
#define FF_CNT (FF_MAX+1)
|
||||||
|
|
||||||
|
#endif /* _UAPI_INPUT_H */
|
||||||
231
include/linux/linux/uinput.h
Normal file
231
include/linux/linux/uinput.h
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
/*
|
||||||
|
* User level driver support for input subsystem
|
||||||
|
*
|
||||||
|
* Heavily based on evdev.c by Vojtech Pavlik
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
|
||||||
|
*
|
||||||
|
* Changes/Revisions:
|
||||||
|
* 0.5 08/13/2015 (David Herrmann <dh.herrmann@gmail.com> &
|
||||||
|
* Benjamin Tissoires <benjamin.tissoires@redhat.com>)
|
||||||
|
* - add UI_DEV_SETUP ioctl
|
||||||
|
* - add UI_ABS_SETUP ioctl
|
||||||
|
* - add UI_GET_VERSION ioctl
|
||||||
|
* 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
|
||||||
|
* - add UI_GET_SYSNAME ioctl
|
||||||
|
* 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
|
||||||
|
* - update ff support for the changes in kernel interface
|
||||||
|
* - add UINPUT_VERSION
|
||||||
|
* 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
|
||||||
|
* - added force feedback support
|
||||||
|
* - added UI_SET_PHYS
|
||||||
|
* 0.1 20/06/2002
|
||||||
|
* - first public version
|
||||||
|
*/
|
||||||
|
#ifndef __UINPUT_H_
|
||||||
|
#define __UINPUT_H_
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
#define UINPUT_VERSION 5
|
||||||
|
#define UINPUT_MAX_NAME_SIZE 80
|
||||||
|
|
||||||
|
struct uinput_ff_upload {
|
||||||
|
__u32 request_id;
|
||||||
|
__s32 retval;
|
||||||
|
struct ff_effect effect;
|
||||||
|
struct ff_effect old;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uinput_ff_erase {
|
||||||
|
__u32 request_id;
|
||||||
|
__s32 retval;
|
||||||
|
__u32 effect_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ioctl */
|
||||||
|
#define UINPUT_IOCTL_BASE 'U'
|
||||||
|
#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
|
||||||
|
#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
|
||||||
|
|
||||||
|
struct uinput_setup {
|
||||||
|
struct input_id id;
|
||||||
|
char name[UINPUT_MAX_NAME_SIZE];
|
||||||
|
__u32 ff_effects_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_DEV_SETUP - Set device parameters for setup
|
||||||
|
*
|
||||||
|
* This ioctl sets parameters for the input device to be created. It
|
||||||
|
* supersedes the old "struct uinput_user_dev" method, which wrote this data
|
||||||
|
* via write(). To actually set the absolute axes UI_ABS_SETUP should be
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* The ioctl takes a "struct uinput_setup" object as argument. The fields of
|
||||||
|
* this object are as follows:
|
||||||
|
* id: See the description of "struct input_id". This field is
|
||||||
|
* copied unchanged into the new device.
|
||||||
|
* name: This is used unchanged as name for the new device.
|
||||||
|
* ff_effects_max: This limits the maximum numbers of force-feedback effects.
|
||||||
|
* See below for a description of FF with uinput.
|
||||||
|
*
|
||||||
|
* This ioctl can be called multiple times and will overwrite previous values.
|
||||||
|
* If this ioctl fails with -EINVAL, it is recommended to use the old
|
||||||
|
* "uinput_user_dev" method via write() as a fallback, in case you run on an
|
||||||
|
* old kernel that does not support this ioctl.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with -EINVAL if it is not supported or if you passed
|
||||||
|
* incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
|
||||||
|
* passed uinput_setup object cannot be read/written.
|
||||||
|
* If this call fails, partial data may have already been applied to the
|
||||||
|
* internal device.
|
||||||
|
*/
|
||||||
|
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
|
||||||
|
|
||||||
|
struct uinput_abs_setup {
|
||||||
|
__u16 code; /* axis code */
|
||||||
|
/* __u16 filler; */
|
||||||
|
struct input_absinfo absinfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_ABS_SETUP - Set absolute axis information for the device to setup
|
||||||
|
*
|
||||||
|
* This ioctl sets one absolute axis information for the input device to be
|
||||||
|
* created. It supersedes the old "struct uinput_user_dev" method, which wrote
|
||||||
|
* part of this data and the content of UI_DEV_SETUP via write().
|
||||||
|
*
|
||||||
|
* The ioctl takes a "struct uinput_abs_setup" object as argument. The fields
|
||||||
|
* of this object are as follows:
|
||||||
|
* code: The corresponding input code associated with this axis
|
||||||
|
* (ABS_X, ABS_Y, etc...)
|
||||||
|
* absinfo: See "struct input_absinfo" for a description of this field.
|
||||||
|
* This field is copied unchanged into the kernel for the
|
||||||
|
* specified axis. If the axis is not enabled via
|
||||||
|
* UI_SET_ABSBIT, this ioctl will enable it.
|
||||||
|
*
|
||||||
|
* This ioctl can be called multiple times and will overwrite previous values.
|
||||||
|
* If this ioctl fails with -EINVAL, it is recommended to use the old
|
||||||
|
* "uinput_user_dev" method via write() as a fallback, in case you run on an
|
||||||
|
* old kernel that does not support this ioctl.
|
||||||
|
*
|
||||||
|
* This ioctl may fail with -EINVAL if it is not supported or if you passed
|
||||||
|
* incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
|
||||||
|
* passed uinput_setup object cannot be read/written.
|
||||||
|
* If this call fails, partial data may have already been applied to the
|
||||||
|
* internal device.
|
||||||
|
*/
|
||||||
|
#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
|
||||||
|
|
||||||
|
#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int)
|
||||||
|
#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int)
|
||||||
|
#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int)
|
||||||
|
#define UI_SET_ABSBIT _IOW(UINPUT_IOCTL_BASE, 103, int)
|
||||||
|
#define UI_SET_MSCBIT _IOW(UINPUT_IOCTL_BASE, 104, int)
|
||||||
|
#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int)
|
||||||
|
#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int)
|
||||||
|
#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
|
||||||
|
#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
|
||||||
|
#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int)
|
||||||
|
#define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int)
|
||||||
|
|
||||||
|
#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
|
||||||
|
#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
|
||||||
|
#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
|
||||||
|
#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_GET_SYSNAME - get the sysfs name of the created uinput device
|
||||||
|
*
|
||||||
|
* @return the sysfs name of the created virtual input device.
|
||||||
|
* The complete sysfs path is then /sys/devices/virtual/input/--NAME--
|
||||||
|
* Usually, it is in the form "inputN"
|
||||||
|
*/
|
||||||
|
#define UI_GET_SYSNAME(len) _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 44, len)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI_GET_VERSION - Return version of uinput protocol
|
||||||
|
*
|
||||||
|
* This writes uinput protocol version implemented by the kernel into
|
||||||
|
* the integer pointed to by the ioctl argument. The protocol version
|
||||||
|
* is hard-coded in the kernel and is independent of the uinput device.
|
||||||
|
*/
|
||||||
|
#define UI_GET_VERSION _IOR(UINPUT_IOCTL_BASE, 45, unsigned int)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To write a force-feedback-capable driver, the upload_effect
|
||||||
|
* and erase_effect callbacks in input_dev must be implemented.
|
||||||
|
* The uinput driver will generate a fake input event when one of
|
||||||
|
* these callbacks are invoked. The userspace code then uses
|
||||||
|
* ioctls to retrieve additional parameters and send the return code.
|
||||||
|
* The callback blocks until this return code is sent.
|
||||||
|
*
|
||||||
|
* The described callback mechanism is only used if ff_effects_max
|
||||||
|
* is set.
|
||||||
|
*
|
||||||
|
* To implement upload_effect():
|
||||||
|
* 1. Wait for an event with type == EV_UINPUT and code == UI_FF_UPLOAD.
|
||||||
|
* A request ID will be given in 'value'.
|
||||||
|
* 2. Allocate a uinput_ff_upload struct, fill in request_id with
|
||||||
|
* the 'value' from the EV_UINPUT event.
|
||||||
|
* 3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the
|
||||||
|
* uinput_ff_upload struct. It will be filled in with the
|
||||||
|
* ff_effects passed to upload_effect().
|
||||||
|
* 4. Perform the effect upload, and place a return code back into
|
||||||
|
the uinput_ff_upload struct.
|
||||||
|
* 5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the
|
||||||
|
* uinput_ff_upload_effect struct. This will complete execution
|
||||||
|
* of our upload_effect() handler.
|
||||||
|
*
|
||||||
|
* To implement erase_effect():
|
||||||
|
* 1. Wait for an event with type == EV_UINPUT and code == UI_FF_ERASE.
|
||||||
|
* A request ID will be given in 'value'.
|
||||||
|
* 2. Allocate a uinput_ff_erase struct, fill in request_id with
|
||||||
|
* the 'value' from the EV_UINPUT event.
|
||||||
|
* 3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the
|
||||||
|
* uinput_ff_erase struct. It will be filled in with the
|
||||||
|
* effect ID passed to erase_effect().
|
||||||
|
* 4. Perform the effect erasure, and place a return code back
|
||||||
|
* into the uinput_ff_erase struct.
|
||||||
|
* 5. Issue a UI_END_FF_ERASE ioctl, also giving it the
|
||||||
|
* uinput_ff_erase_effect struct. This will complete execution
|
||||||
|
* of our erase_effect() handler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the new event type, used only by uinput.
|
||||||
|
* 'code' is UI_FF_UPLOAD or UI_FF_ERASE, and 'value'
|
||||||
|
* is the unique request ID. This number was picked
|
||||||
|
* arbitrarily, above EV_MAX (since the input system
|
||||||
|
* never sees it) but in the range of a 16-bit int.
|
||||||
|
*/
|
||||||
|
#define EV_UINPUT 0x0101
|
||||||
|
#define UI_FF_UPLOAD 1
|
||||||
|
#define UI_FF_ERASE 2
|
||||||
|
|
||||||
|
struct uinput_user_dev {
|
||||||
|
char name[UINPUT_MAX_NAME_SIZE];
|
||||||
|
struct input_id id;
|
||||||
|
__u32 ff_effects_max;
|
||||||
|
__s32 absmax[ABS_CNT];
|
||||||
|
__s32 absmin[ABS_CNT];
|
||||||
|
__s32 absfuzz[ABS_CNT];
|
||||||
|
__s32 absflat[ABS_CNT];
|
||||||
|
};
|
||||||
|
#endif /* __UINPUT_H_ */
|
||||||
|
|
@ -1,231 +1,5 @@
|
||||||
/*
|
#ifdef __linux__
|
||||||
* User level driver support for input subsystem
|
#include "linux/uinput.h"
|
||||||
*
|
#elif __FreeBSD__
|
||||||
* Heavily based on evdev.c by Vojtech Pavlik
|
#include "freebsd/uinput.h"
|
||||||
*
|
#endif
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
|
|
||||||
*
|
|
||||||
* Changes/Revisions:
|
|
||||||
* 0.5 08/13/2015 (David Herrmann <dh.herrmann@gmail.com> &
|
|
||||||
* Benjamin Tissoires <benjamin.tissoires@redhat.com>)
|
|
||||||
* - add UI_DEV_SETUP ioctl
|
|
||||||
* - add UI_ABS_SETUP ioctl
|
|
||||||
* - add UI_GET_VERSION ioctl
|
|
||||||
* 0.4 01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
|
|
||||||
* - add UI_GET_SYSNAME ioctl
|
|
||||||
* 0.3 24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
|
|
||||||
* - update ff support for the changes in kernel interface
|
|
||||||
* - add UINPUT_VERSION
|
|
||||||
* 0.2 16/10/2004 (Micah Dowty <micah@navi.cx>)
|
|
||||||
* - added force feedback support
|
|
||||||
* - added UI_SET_PHYS
|
|
||||||
* 0.1 20/06/2002
|
|
||||||
* - first public version
|
|
||||||
*/
|
|
||||||
#ifndef __UINPUT_H_
|
|
||||||
#define __UINPUT_H_
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/input.h>
|
|
||||||
|
|
||||||
#define UINPUT_VERSION 5
|
|
||||||
#define UINPUT_MAX_NAME_SIZE 80
|
|
||||||
|
|
||||||
struct uinput_ff_upload {
|
|
||||||
__u32 request_id;
|
|
||||||
__s32 retval;
|
|
||||||
struct ff_effect effect;
|
|
||||||
struct ff_effect old;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct uinput_ff_erase {
|
|
||||||
__u32 request_id;
|
|
||||||
__s32 retval;
|
|
||||||
__u32 effect_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ioctl */
|
|
||||||
#define UINPUT_IOCTL_BASE 'U'
|
|
||||||
#define UI_DEV_CREATE _IO(UINPUT_IOCTL_BASE, 1)
|
|
||||||
#define UI_DEV_DESTROY _IO(UINPUT_IOCTL_BASE, 2)
|
|
||||||
|
|
||||||
struct uinput_setup {
|
|
||||||
struct input_id id;
|
|
||||||
char name[UINPUT_MAX_NAME_SIZE];
|
|
||||||
__u32 ff_effects_max;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UI_DEV_SETUP - Set device parameters for setup
|
|
||||||
*
|
|
||||||
* This ioctl sets parameters for the input device to be created. It
|
|
||||||
* supersedes the old "struct uinput_user_dev" method, which wrote this data
|
|
||||||
* via write(). To actually set the absolute axes UI_ABS_SETUP should be
|
|
||||||
* used.
|
|
||||||
*
|
|
||||||
* The ioctl takes a "struct uinput_setup" object as argument. The fields of
|
|
||||||
* this object are as follows:
|
|
||||||
* id: See the description of "struct input_id". This field is
|
|
||||||
* copied unchanged into the new device.
|
|
||||||
* name: This is used unchanged as name for the new device.
|
|
||||||
* ff_effects_max: This limits the maximum numbers of force-feedback effects.
|
|
||||||
* See below for a description of FF with uinput.
|
|
||||||
*
|
|
||||||
* This ioctl can be called multiple times and will overwrite previous values.
|
|
||||||
* If this ioctl fails with -EINVAL, it is recommended to use the old
|
|
||||||
* "uinput_user_dev" method via write() as a fallback, in case you run on an
|
|
||||||
* old kernel that does not support this ioctl.
|
|
||||||
*
|
|
||||||
* This ioctl may fail with -EINVAL if it is not supported or if you passed
|
|
||||||
* incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
|
|
||||||
* passed uinput_setup object cannot be read/written.
|
|
||||||
* If this call fails, partial data may have already been applied to the
|
|
||||||
* internal device.
|
|
||||||
*/
|
|
||||||
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
|
|
||||||
|
|
||||||
struct uinput_abs_setup {
|
|
||||||
__u16 code; /* axis code */
|
|
||||||
/* __u16 filler; */
|
|
||||||
struct input_absinfo absinfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UI_ABS_SETUP - Set absolute axis information for the device to setup
|
|
||||||
*
|
|
||||||
* This ioctl sets one absolute axis information for the input device to be
|
|
||||||
* created. It supersedes the old "struct uinput_user_dev" method, which wrote
|
|
||||||
* part of this data and the content of UI_DEV_SETUP via write().
|
|
||||||
*
|
|
||||||
* The ioctl takes a "struct uinput_abs_setup" object as argument. The fields
|
|
||||||
* of this object are as follows:
|
|
||||||
* code: The corresponding input code associated with this axis
|
|
||||||
* (ABS_X, ABS_Y, etc...)
|
|
||||||
* absinfo: See "struct input_absinfo" for a description of this field.
|
|
||||||
* This field is copied unchanged into the kernel for the
|
|
||||||
* specified axis. If the axis is not enabled via
|
|
||||||
* UI_SET_ABSBIT, this ioctl will enable it.
|
|
||||||
*
|
|
||||||
* This ioctl can be called multiple times and will overwrite previous values.
|
|
||||||
* If this ioctl fails with -EINVAL, it is recommended to use the old
|
|
||||||
* "uinput_user_dev" method via write() as a fallback, in case you run on an
|
|
||||||
* old kernel that does not support this ioctl.
|
|
||||||
*
|
|
||||||
* This ioctl may fail with -EINVAL if it is not supported or if you passed
|
|
||||||
* incorrect values, -ENOMEM if the kernel runs out of memory or -EFAULT if the
|
|
||||||
* passed uinput_setup object cannot be read/written.
|
|
||||||
* If this call fails, partial data may have already been applied to the
|
|
||||||
* internal device.
|
|
||||||
*/
|
|
||||||
#define UI_ABS_SETUP _IOW(UINPUT_IOCTL_BASE, 4, struct uinput_abs_setup)
|
|
||||||
|
|
||||||
#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int)
|
|
||||||
#define UI_SET_KEYBIT _IOW(UINPUT_IOCTL_BASE, 101, int)
|
|
||||||
#define UI_SET_RELBIT _IOW(UINPUT_IOCTL_BASE, 102, int)
|
|
||||||
#define UI_SET_ABSBIT _IOW(UINPUT_IOCTL_BASE, 103, int)
|
|
||||||
#define UI_SET_MSCBIT _IOW(UINPUT_IOCTL_BASE, 104, int)
|
|
||||||
#define UI_SET_LEDBIT _IOW(UINPUT_IOCTL_BASE, 105, int)
|
|
||||||
#define UI_SET_SNDBIT _IOW(UINPUT_IOCTL_BASE, 106, int)
|
|
||||||
#define UI_SET_FFBIT _IOW(UINPUT_IOCTL_BASE, 107, int)
|
|
||||||
#define UI_SET_PHYS _IOW(UINPUT_IOCTL_BASE, 108, char*)
|
|
||||||
#define UI_SET_SWBIT _IOW(UINPUT_IOCTL_BASE, 109, int)
|
|
||||||
#define UI_SET_PROPBIT _IOW(UINPUT_IOCTL_BASE, 110, int)
|
|
||||||
|
|
||||||
#define UI_BEGIN_FF_UPLOAD _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
|
|
||||||
#define UI_END_FF_UPLOAD _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
|
|
||||||
#define UI_BEGIN_FF_ERASE _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
|
|
||||||
#define UI_END_FF_ERASE _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UI_GET_SYSNAME - get the sysfs name of the created uinput device
|
|
||||||
*
|
|
||||||
* @return the sysfs name of the created virtual input device.
|
|
||||||
* The complete sysfs path is then /sys/devices/virtual/input/--NAME--
|
|
||||||
* Usually, it is in the form "inputN"
|
|
||||||
*/
|
|
||||||
#define UI_GET_SYSNAME(len) _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 44, len)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UI_GET_VERSION - Return version of uinput protocol
|
|
||||||
*
|
|
||||||
* This writes uinput protocol version implemented by the kernel into
|
|
||||||
* the integer pointed to by the ioctl argument. The protocol version
|
|
||||||
* is hard-coded in the kernel and is independent of the uinput device.
|
|
||||||
*/
|
|
||||||
#define UI_GET_VERSION _IOR(UINPUT_IOCTL_BASE, 45, unsigned int)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To write a force-feedback-capable driver, the upload_effect
|
|
||||||
* and erase_effect callbacks in input_dev must be implemented.
|
|
||||||
* The uinput driver will generate a fake input event when one of
|
|
||||||
* these callbacks are invoked. The userspace code then uses
|
|
||||||
* ioctls to retrieve additional parameters and send the return code.
|
|
||||||
* The callback blocks until this return code is sent.
|
|
||||||
*
|
|
||||||
* The described callback mechanism is only used if ff_effects_max
|
|
||||||
* is set.
|
|
||||||
*
|
|
||||||
* To implement upload_effect():
|
|
||||||
* 1. Wait for an event with type == EV_UINPUT and code == UI_FF_UPLOAD.
|
|
||||||
* A request ID will be given in 'value'.
|
|
||||||
* 2. Allocate a uinput_ff_upload struct, fill in request_id with
|
|
||||||
* the 'value' from the EV_UINPUT event.
|
|
||||||
* 3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the
|
|
||||||
* uinput_ff_upload struct. It will be filled in with the
|
|
||||||
* ff_effects passed to upload_effect().
|
|
||||||
* 4. Perform the effect upload, and place a return code back into
|
|
||||||
the uinput_ff_upload struct.
|
|
||||||
* 5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the
|
|
||||||
* uinput_ff_upload_effect struct. This will complete execution
|
|
||||||
* of our upload_effect() handler.
|
|
||||||
*
|
|
||||||
* To implement erase_effect():
|
|
||||||
* 1. Wait for an event with type == EV_UINPUT and code == UI_FF_ERASE.
|
|
||||||
* A request ID will be given in 'value'.
|
|
||||||
* 2. Allocate a uinput_ff_erase struct, fill in request_id with
|
|
||||||
* the 'value' from the EV_UINPUT event.
|
|
||||||
* 3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the
|
|
||||||
* uinput_ff_erase struct. It will be filled in with the
|
|
||||||
* effect ID passed to erase_effect().
|
|
||||||
* 4. Perform the effect erasure, and place a return code back
|
|
||||||
* into the uinput_ff_erase struct.
|
|
||||||
* 5. Issue a UI_END_FF_ERASE ioctl, also giving it the
|
|
||||||
* uinput_ff_erase_effect struct. This will complete execution
|
|
||||||
* of our erase_effect() handler.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the new event type, used only by uinput.
|
|
||||||
* 'code' is UI_FF_UPLOAD or UI_FF_ERASE, and 'value'
|
|
||||||
* is the unique request ID. This number was picked
|
|
||||||
* arbitrarily, above EV_MAX (since the input system
|
|
||||||
* never sees it) but in the range of a 16-bit int.
|
|
||||||
*/
|
|
||||||
#define EV_UINPUT 0x0101
|
|
||||||
#define UI_FF_UPLOAD 1
|
|
||||||
#define UI_FF_ERASE 2
|
|
||||||
|
|
||||||
struct uinput_user_dev {
|
|
||||||
char name[UINPUT_MAX_NAME_SIZE];
|
|
||||||
struct input_id id;
|
|
||||||
__u32 ff_effects_max;
|
|
||||||
__s32 absmax[ABS_CNT];
|
|
||||||
__s32 absmin[ABS_CNT];
|
|
||||||
__s32 absfuzz[ABS_CNT];
|
|
||||||
__s32 absflat[ABS_CNT];
|
|
||||||
};
|
|
||||||
#endif /* __UINPUT_H_ */
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
lib_LTLIBRARIES=libevdev.la
|
lib_LTLIBRARIES=libevdev.la
|
||||||
|
|
||||||
AM_CPPFLAGS = $(GCC_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)
|
AM_CPPFLAGS = $(GCC_CFLAGS) $(GCOV_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)
|
||||||
|
AM_LDFLAGS = $(GCOV_LDFLAGS)
|
||||||
|
|
||||||
libevdev_la_SOURCES = \
|
libevdev_la_SOURCES = \
|
||||||
libevdev.h \
|
libevdev.h \
|
||||||
|
|
@ -11,11 +12,14 @@ libevdev_la_SOURCES = \
|
||||||
libevdev-uinput-int.h \
|
libevdev-uinput-int.h \
|
||||||
libevdev.c \
|
libevdev.c \
|
||||||
libevdev-names.c \
|
libevdev-names.c \
|
||||||
../include/linux/input-event-codes.h \
|
../include/linux/input.h \
|
||||||
../include/linux/input.h
|
../include/linux/uinput.h \
|
||||||
../include/linux/uinput.h
|
../include/linux/@OS@/input-event-codes.h \
|
||||||
|
../include/linux/@OS@/input.h \
|
||||||
|
../include/linux/@OS@/uinput.h
|
||||||
|
|
||||||
libevdev_la_LDFLAGS = \
|
libevdev_la_LDFLAGS = \
|
||||||
|
$(AM_LDFLAGS) \
|
||||||
-version-info $(LIBEVDEV_LT_VERSION) \
|
-version-info $(LIBEVDEV_LT_VERSION) \
|
||||||
-Wl,--version-script="$(srcdir)/libevdev.sym" \
|
-Wl,--version-script="$(srcdir)/libevdev.sym" \
|
||||||
$(GNU_LD_FLAGS)
|
$(GNU_LD_FLAGS)
|
||||||
|
|
@ -26,10 +30,13 @@ libevdevincludedir = $(includedir)/libevdev-1.0/libevdev
|
||||||
libevdevinclude_HEADERS = libevdev.h libevdev-uinput.h
|
libevdevinclude_HEADERS = libevdev.h libevdev-uinput.h
|
||||||
|
|
||||||
event-names.h: Makefile make-event-names.py
|
event-names.h: Makefile make-event-names.py
|
||||||
$(CAT) $(top_srcdir)/include/linux/input.h $(top_srcdir)/include/linux/input-event-codes.h | $(PYTHON) $(srcdir)/make-event-names.py > $@
|
$(PYTHON) $(srcdir)/make-event-names.py $(top_srcdir)/include/linux/@OS@/input.h $(top_srcdir)/include/linux/@OS@/input-event-codes.h > $@
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = make-event-names.py libevdev.sym
|
EXTRA_DIST = make-event-names.py libevdev.sym ../include
|
||||||
CLEANFILES = event-names.h
|
CLEANFILES = event-names.h
|
||||||
BUILT_SOURCES = event-names.h
|
BUILT_SOURCES = event-names.h
|
||||||
|
|
||||||
|
if GCOV_ENABLED
|
||||||
|
CLEANFILES += *.gcno
|
||||||
|
endif
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,12 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIBEVDEV_INT_H
|
#ifndef LIBEVDEV_INT_H
|
||||||
#define LIBEVDEV_INT_H
|
#define LIBEVDEV_INT_H
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -55,11 +38,6 @@ enum SyncState {
|
||||||
SYNC_IN_PROGRESS,
|
SYNC_IN_PROGRESS,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_sync_state {
|
|
||||||
int code;
|
|
||||||
int val[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal only: log data used to send messages to the respective log
|
* Internal only: log data used to send messages to the respective log
|
||||||
* handler. We re-use the same struct for a global and inside
|
* handler. We re-use the same struct for a global and inside
|
||||||
|
|
@ -112,15 +90,6 @@ struct libevdev {
|
||||||
|
|
||||||
struct timeval last_event_time;
|
struct timeval last_event_time;
|
||||||
|
|
||||||
struct {
|
|
||||||
struct mt_sync_state *mt_state;
|
|
||||||
size_t mt_state_sz; /* in bytes */
|
|
||||||
unsigned long *slot_update;
|
|
||||||
size_t slot_update_sz; /* in bytes */
|
|
||||||
unsigned long *tracking_id_changes;
|
|
||||||
size_t tracking_id_changes_sz; /* in bytes */
|
|
||||||
} mt_sync;
|
|
||||||
|
|
||||||
struct logdata log;
|
struct logdata log;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -143,6 +112,16 @@ _libevdev_log_msg(const struct libevdev *dev,
|
||||||
extern enum libevdev_log_priority
|
extern enum libevdev_log_priority
|
||||||
_libevdev_log_priority(const struct libevdev *dev);
|
_libevdev_log_priority(const struct libevdev *dev);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
init_event(struct libevdev *dev, struct input_event *ev, int type, int code, int value)
|
||||||
|
{
|
||||||
|
ev->input_event_sec = dev->last_event_time.tv_sec;
|
||||||
|
ev->input_event_usec = dev->last_event_time.tv_usec;
|
||||||
|
ev->type = type;
|
||||||
|
ev->code = code;
|
||||||
|
ev->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a pointer to the next element in the queue, or NULL if the queue
|
* @return a pointer to the next element in the queue, or NULL if the queue
|
||||||
* is full.
|
* is full.
|
||||||
|
|
@ -156,6 +135,18 @@ queue_push(struct libevdev *dev)
|
||||||
return &dev->queue[dev->queue_next++];
|
return &dev->queue[dev->queue_next++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
queue_push_event(struct libevdev *dev, unsigned int type,
|
||||||
|
unsigned int code, int value)
|
||||||
|
{
|
||||||
|
struct input_event *ev = queue_push(dev);
|
||||||
|
|
||||||
|
if (ev)
|
||||||
|
init_event(dev, ev, type, code, value);
|
||||||
|
|
||||||
|
return ev != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set ev to the last element in the queue, removing it from the queue.
|
* Set ev to the last element in the queue, removing it from the queue.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,18 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
* Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include "libevdev.h"
|
|
||||||
#include "libevdev-int.h"
|
#include "libevdev-int.h"
|
||||||
#include "libevdev-util.h"
|
#include "libevdev-util.h"
|
||||||
|
#include "libevdev.h"
|
||||||
|
|
||||||
#include "event-names.h"
|
#include "event-names.h"
|
||||||
|
|
||||||
struct name_lookup {
|
struct name_lookup {
|
||||||
|
|
@ -142,6 +126,29 @@ libevdev_event_code_from_name_n(unsigned int type, const char *name, size_t len)
|
||||||
return entry ? (int)entry->value : -1;
|
return entry ? (int)entry->value : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_event_value_from_name(unsigned int type, unsigned int code, const char *name)
|
||||||
|
{
|
||||||
|
return libevdev_event_value_from_name_n(type, code, name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_event_value_from_name_n(unsigned int type, unsigned int code, const char *name, size_t len)
|
||||||
|
{
|
||||||
|
struct name_lookup lookup;
|
||||||
|
const struct name_entry *entry;
|
||||||
|
|
||||||
|
if (type != EV_ABS || code != ABS_MT_TOOL_TYPE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
lookup.name = name;
|
||||||
|
lookup.len = len;
|
||||||
|
|
||||||
|
entry = lookup_name(tool_type_names, ARRAY_LENGTH(tool_type_names), &lookup);
|
||||||
|
|
||||||
|
return entry ? (int)entry->value : -1;
|
||||||
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT int
|
LIBEVDEV_EXPORT int
|
||||||
libevdev_property_from_name(const char *name)
|
libevdev_property_from_name(const char *name)
|
||||||
{
|
{
|
||||||
|
|
@ -161,3 +168,46 @@ libevdev_property_from_name_n(const char *name, size_t len)
|
||||||
|
|
||||||
return entry ? (int)entry->value : -1;
|
return entry ? (int)entry->value : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_event_code_from_code_name(const char *name)
|
||||||
|
{
|
||||||
|
return libevdev_event_code_from_code_name_n(name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_event_code_from_code_name_n(const char *name, size_t len)
|
||||||
|
{
|
||||||
|
const struct name_entry *entry;
|
||||||
|
struct name_lookup lookup;
|
||||||
|
|
||||||
|
/* now look up the name @name and return the constant */
|
||||||
|
lookup.name = name;
|
||||||
|
lookup.len = len;
|
||||||
|
|
||||||
|
entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
|
||||||
|
|
||||||
|
return entry ? (int)entry->value : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_event_type_from_code_name(const char *name)
|
||||||
|
{
|
||||||
|
return libevdev_event_type_from_code_name_n(name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_event_type_from_code_name_n(const char *name, size_t len)
|
||||||
|
{
|
||||||
|
const struct name_entry *entry;
|
||||||
|
struct name_lookup lookup;
|
||||||
|
|
||||||
|
/* First look up if the name exists, we dont' want to return a valid
|
||||||
|
* type for an invalid code name */
|
||||||
|
lookup.name = name;
|
||||||
|
lookup.len = len;
|
||||||
|
|
||||||
|
entry = lookup_name(code_names, ARRAY_LENGTH(code_names), &lookup);
|
||||||
|
|
||||||
|
return entry ? type_from_prefix(name, len) : -1;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct libevdev_uinput {
|
struct libevdev_uinput {
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,25 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <fcntl.h>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <linux/uinput.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libevdev.h"
|
|
||||||
#include "libevdev-int.h"
|
#include "libevdev-int.h"
|
||||||
#include "libevdev-uinput.h"
|
|
||||||
#include "libevdev-uinput-int.h"
|
#include "libevdev-uinput-int.h"
|
||||||
|
#include "libevdev-uinput.h"
|
||||||
#include "libevdev-util.h"
|
#include "libevdev-util.h"
|
||||||
|
#include "libevdev.h"
|
||||||
#define SYS_INPUT_DIR "/sys/devices/virtual/input/"
|
|
||||||
|
|
||||||
#ifndef UINPUT_IOCTL_BASE
|
#ifndef UINPUT_IOCTL_BASE
|
||||||
#define UINPUT_IOCTL_BASE 'U'
|
#define UINPUT_IOCTL_BASE 'U'
|
||||||
|
|
@ -182,6 +163,35 @@ libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev)
|
||||||
return uinput_dev->fd;
|
return uinput_dev->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
/*
|
||||||
|
* FreeBSD does not have anything similar to sysfs.
|
||||||
|
* Set libevdev_uinput->syspath to NULL unconditionally.
|
||||||
|
* Look up the device nodes directly instead of via sysfs, as this matches what
|
||||||
|
* is returned by the UI_GET_SYSNAME ioctl() on FreeBSD.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
||||||
|
{
|
||||||
|
#define DEV_INPUT_DIR "/dev/input/"
|
||||||
|
int rc;
|
||||||
|
char buf[sizeof(DEV_INPUT_DIR) + 64] = DEV_INPUT_DIR;
|
||||||
|
|
||||||
|
rc = ioctl(uinput_dev->fd,
|
||||||
|
UI_GET_SYSNAME(sizeof(buf) - strlen(DEV_INPUT_DIR)),
|
||||||
|
&buf[strlen(DEV_INPUT_DIR)]);
|
||||||
|
if (rc == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uinput_dev->syspath = NULL;
|
||||||
|
uinput_dev->devnode = strdup(buf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#undef DEV_INPUT_DIR
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !__FreeBSD__ */
|
||||||
|
|
||||||
static int is_event_device(const struct dirent *dent) {
|
static int is_event_device(const struct dirent *dent) {
|
||||||
return strncmp("event", dent->d_name, 5) == 0;
|
return strncmp("event", dent->d_name, 5) == 0;
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +227,7 @@ static int is_input_device(const struct dirent *dent) {
|
||||||
static int
|
static int
|
||||||
fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
||||||
{
|
{
|
||||||
|
#define SYS_INPUT_DIR "/sys/devices/virtual/input/"
|
||||||
struct dirent **namelist;
|
struct dirent **namelist;
|
||||||
int ndev, i;
|
int ndev, i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
@ -270,18 +281,19 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
||||||
/* FIXME: could descend into bit comparison here */
|
/* FIXME: could descend into bit comparison here */
|
||||||
log_info(NULL, "multiple identical devices found. syspath is unreliable\n");
|
log_info(NULL, "multiple identical devices found. syspath is unreliable\n");
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
rc = snprintf(buf, sizeof(buf), "%s%s",
|
|
||||||
SYS_INPUT_DIR,
|
|
||||||
namelist[i]->d_name);
|
|
||||||
if (rc < 0 || (size_t)rc >= sizeof(buf)) {
|
|
||||||
log_error(NULL, "Invalid syspath, syspath is unreliable\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uinput_dev->syspath = strdup(buf);
|
|
||||||
uinput_dev->devnode = fetch_device_node(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = snprintf(buf, sizeof(buf), "%s%s",
|
||||||
|
SYS_INPUT_DIR,
|
||||||
|
namelist[i]->d_name);
|
||||||
|
|
||||||
|
if (rc < 0 || (size_t)rc >= sizeof(buf)) {
|
||||||
|
log_error(NULL, "Invalid syspath, syspath is unreliable\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uinput_dev->syspath = strdup(buf);
|
||||||
|
uinput_dev->devnode = fetch_device_node(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,11 +302,12 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
||||||
free(namelist);
|
free(namelist);
|
||||||
|
|
||||||
return uinput_dev->devnode ? 0 : -1;
|
return uinput_dev->devnode ? 0 : -1;
|
||||||
|
#undef SYS_INPUT_DIR
|
||||||
}
|
}
|
||||||
|
#endif /* __FreeBSD__*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
uinput_create_write(const struct libevdev *dev, int fd,
|
uinput_create_write(const struct libevdev *dev, int fd)
|
||||||
struct libevdev_uinput *new_device)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct uinput_user_dev uidev;
|
struct uinput_user_dev uidev;
|
||||||
|
|
@ -313,9 +326,9 @@ uinput_create_write(const struct libevdev *dev, int fd,
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
rc = write(fd, &uidev, sizeof(uidev));
|
rc = write(fd, &uidev, sizeof(uidev));
|
||||||
if (rc < 0)
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
else if ((size_t)rc < sizeof(uidev)) {
|
} else if ((size_t)rc < sizeof(uidev)) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
@ -381,7 +394,7 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li
|
||||||
uinput_version >= 5)
|
uinput_version >= 5)
|
||||||
rc = uinput_create_DEV_SETUP(dev, fd, new_device);
|
rc = uinput_create_DEV_SETUP(dev, fd, new_device);
|
||||||
else
|
else
|
||||||
rc = uinput_create_write(dev, fd, new_device);
|
rc = uinput_create_write(dev, fd);
|
||||||
|
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
@ -455,7 +468,13 @@ libevdev_uinput_write_event(const struct libevdev_uinput *uinput_dev,
|
||||||
unsigned int code,
|
unsigned int code,
|
||||||
int value)
|
int value)
|
||||||
{
|
{
|
||||||
struct input_event ev = { {0,0}, type, code, value };
|
struct input_event ev = {
|
||||||
|
.input_event_sec = 0,
|
||||||
|
.input_event_usec = 0,
|
||||||
|
.type = type,
|
||||||
|
.code = code,
|
||||||
|
.value = value
|
||||||
|
};
|
||||||
int fd = libevdev_uinput_get_fd(uinput_dev);
|
int fd = libevdev_uinput_get_fd(uinput_dev);
|
||||||
int rc, max;
|
int rc, max;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,25 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* of this software and associated documentation files (the "Software"), to
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
* deal in the Software without restriction, including without limitation the
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
* that the name of the copyright holders not be used in advertising or
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
* publicity pertaining to distribution of the software without specific,
|
* furnished to do so, subject to the following conditions:
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
*
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
* The above copyright notice and this permission notice (including the next
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
* Software.
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
*
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* OF THIS SOFTWARE.
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIBEVDEV_UINPUT_H
|
#ifndef LIBEVDEV_UINPUT_H
|
||||||
|
|
@ -40,21 +42,20 @@ struct libevdev_uinput;
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* int err;
|
* int err;
|
||||||
* int fd, new_fd, uifd;
|
* int fd, uifd;
|
||||||
* struct libevdev *dev;
|
* struct libevdev *dev;
|
||||||
* struct libevdev_uinput *uidev;
|
* struct libevdev_uinput *uidev;
|
||||||
* struct input_event ev[2];
|
|
||||||
*
|
*
|
||||||
* fd = open("/dev/input/event0", O_RDONLY);
|
* fd = open("/dev/input/event0", O_RDONLY);
|
||||||
* if (fd < 0)
|
* if (fd < 0)
|
||||||
* return err;
|
* return -errno;
|
||||||
*
|
*
|
||||||
* err = libevdev_new_from_fd(fd, &dev);
|
* err = libevdev_new_from_fd(fd, &dev);
|
||||||
* if (err != 0)
|
* if (err != 0)
|
||||||
* return err;
|
* return err;
|
||||||
*
|
*
|
||||||
* uifd = open("/dev/uinput", O_RDWR);
|
* uifd = open("/dev/uinput", O_RDWR);
|
||||||
* if (uidev < 0)
|
* if (uifd < 0)
|
||||||
* return -errno;
|
* return -errno;
|
||||||
*
|
*
|
||||||
* err = libevdev_uinput_create_from_device(dev, uifd, &uidev);
|
* err = libevdev_uinput_create_from_device(dev, uifd, &uidev);
|
||||||
|
|
@ -65,7 +66,7 @@ struct libevdev_uinput;
|
||||||
* err = libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
* err = libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
||||||
* if (err != 0)
|
* if (err != 0)
|
||||||
* return err;
|
* return err;
|
||||||
* libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
* err = libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
* if (err != 0)
|
* if (err != 0)
|
||||||
* return err;
|
* return err;
|
||||||
*
|
*
|
||||||
|
|
@ -107,7 +108,7 @@ struct libevdev_uinput;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum libevdev_uinput_open_mode {
|
enum libevdev_uinput_open_mode {
|
||||||
/* intentionally -2 to avoid to avoid code like the below from accidentally working:
|
/* intentionally -2 to avoid code like below from accidentally working:
|
||||||
fd = open("/dev/uinput", O_RDWR); // fails, fd is -1
|
fd = open("/dev/uinput", O_RDWR); // fails, fd is -1
|
||||||
libevdev_uinput_create_from_device(dev, fd, &uidev); // may hide the error */
|
libevdev_uinput_create_from_device(dev, fd, &uidev); // may hide the error */
|
||||||
LIBEVDEV_UINPUT_OPEN_MANAGED = -2 /**< let libevdev open and close @c /dev/uinput */
|
LIBEVDEV_UINPUT_OPEN_MANAGED = -2 /**< let libevdev open and close @c /dev/uinput */
|
||||||
|
|
@ -138,6 +139,9 @@ enum libevdev_uinput_open_mode {
|
||||||
* REP_PERIOD will default to the kernel defaults, not to the ones set in the
|
* REP_PERIOD will default to the kernel defaults, not to the ones set in the
|
||||||
* source device.
|
* source device.
|
||||||
*
|
*
|
||||||
|
* @note On FreeBSD, if the UI_GET_SYSNAME ioctl() fails, there is no other way
|
||||||
|
* to get a device, and the function call will fail.
|
||||||
|
*
|
||||||
* @param dev The device to duplicate
|
* @param dev The device to duplicate
|
||||||
* @param uinput_fd @ref LIBEVDEV_UINPUT_OPEN_MANAGED or a file descriptor to @c /dev/uinput,
|
* @param uinput_fd @ref LIBEVDEV_UINPUT_OPEN_MANAGED or a file descriptor to @c /dev/uinput,
|
||||||
* @param[out] uinput_dev The newly created libevdev device.
|
* @param[out] uinput_dev The newly created libevdev device.
|
||||||
|
|
@ -183,13 +187,21 @@ int libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev);
|
||||||
* @ingroup uinput
|
* @ingroup uinput
|
||||||
*
|
*
|
||||||
* Return the syspath representing this uinput device. If the UI_GET_SYSNAME
|
* Return the syspath representing this uinput device. If the UI_GET_SYSNAME
|
||||||
* ioctl not available, libevdev makes an educated guess.
|
* ioctl is not available, libevdev makes an educated guess.
|
||||||
* The UI_GET_SYSNAME ioctl is available since Linux 3.15.
|
* The UI_GET_SYSNAME ioctl is available since Linux 3.15.
|
||||||
*
|
*
|
||||||
|
* The syspath returned is the one of the input node itself
|
||||||
|
* (e.g. /sys/devices/virtual/input/input123), not the syspath of the device
|
||||||
|
* node returned with libevdev_uinput_get_devnode().
|
||||||
|
*
|
||||||
* @note This function may return NULL if UI_GET_SYSNAME is not available.
|
* @note This function may return NULL if UI_GET_SYSNAME is not available.
|
||||||
* In that case, libevdev uses ctime and the device name to guess devices.
|
* In that case, libevdev uses ctime and the device name to guess devices.
|
||||||
* To avoid false positives, wait at least wait at least 1.5s between
|
* To avoid false positives, wait at least 1.5s between creating devices that
|
||||||
* creating devices that have the same name.
|
* have the same name.
|
||||||
|
*
|
||||||
|
* @note FreeBSD does not have sysfs, on FreeBSD this function always returns
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
* @param uinput_dev A previously created uinput device.
|
* @param uinput_dev A previously created uinput device.
|
||||||
* @return The syspath for this device, including the preceding /sys
|
* @return The syspath for this device, including the preceding /sys
|
||||||
*
|
*
|
||||||
|
|
@ -207,6 +219,11 @@ const char* libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev);
|
||||||
*
|
*
|
||||||
* @note This function may return NULL. libevdev may have to guess the
|
* @note This function may return NULL. libevdev may have to guess the
|
||||||
* syspath and the device node. See libevdev_uinput_get_syspath() for details.
|
* syspath and the device node. See libevdev_uinput_get_syspath() for details.
|
||||||
|
*
|
||||||
|
* @note On FreeBSD, this function can not return NULL. libudev uses the
|
||||||
|
* UI_GET_SYSNAME ioctl to get the device node on this platform and if that
|
||||||
|
* fails, the call to libevdev_uinput_create_from_device() fails.
|
||||||
|
*
|
||||||
* @param uinput_dev A previously created uinput device.
|
* @param uinput_dev A previously created uinput device.
|
||||||
* @return The device node for this device, in the form of /dev/input/eventN
|
* @return The device node for this device, in the form of /dev/input/eventN
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,12 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _UTIL_H_
|
#ifndef _UTIL_H_
|
||||||
#define _UTIL_H_
|
#define _UTIL_H_
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
@ -34,6 +17,7 @@
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
|
#ifdef __GNUC__
|
||||||
#define min(a,b) \
|
#define min(a,b) \
|
||||||
({ __typeof__ (a) _a = (a); \
|
({ __typeof__ (a) _a = (a); \
|
||||||
__typeof__ (b) _b = (b); \
|
__typeof__ (b) _b = (b); \
|
||||||
|
|
@ -44,6 +28,10 @@
|
||||||
__typeof__ (b) _b = (b); \
|
__typeof__ (b) _b = (b); \
|
||||||
_a > _b ? _a : _b; \
|
_a > _b ? _a : _b; \
|
||||||
})
|
})
|
||||||
|
#else
|
||||||
|
#define min(a,b) ((a) > (b) ? (b) : (a))
|
||||||
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
startswith(const char *str, size_t len, const char *prefix, size_t plen)
|
startswith(const char *str, size_t len, const char *prefix, size_t plen)
|
||||||
|
|
@ -54,19 +42,19 @@ startswith(const char *str, size_t len, const char *prefix, size_t plen)
|
||||||
static inline int
|
static inline int
|
||||||
bit_is_set(const unsigned long *array, int bit)
|
bit_is_set(const unsigned long *array, int bit)
|
||||||
{
|
{
|
||||||
return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
|
return !!(array[bit / LONG_BITS] & (1ULL << (bit % LONG_BITS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_bit(unsigned long *array, int bit)
|
set_bit(unsigned long *array, int bit)
|
||||||
{
|
{
|
||||||
array[bit / LONG_BITS] |= (1LL << (bit % LONG_BITS));
|
array[bit / LONG_BITS] |= (1ULL << (bit % LONG_BITS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
clear_bit(unsigned long *array, int bit)
|
clear_bit(unsigned long *array, int bit)
|
||||||
{
|
{
|
||||||
array[bit / LONG_BITS] &= ~(1LL << (bit % LONG_BITS));
|
array[bit / LONG_BITS] &= ~(1ULL << (bit % LONG_BITS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,23 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#include <poll.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "libevdev.h"
|
|
||||||
#include "libevdev-int.h"
|
#include "libevdev-int.h"
|
||||||
#include "libevdev-util.h"
|
#include "libevdev-util.h"
|
||||||
|
#include "libevdev.h"
|
||||||
|
|
||||||
#include "event-names.h"
|
#include "event-names.h"
|
||||||
|
|
||||||
#define MAXEVENTS 64
|
#define MAXEVENTS 64
|
||||||
|
|
@ -43,7 +28,26 @@ enum event_filter_status {
|
||||||
EVENT_FILTER_DISCARD, /**< Discard current event */
|
EVENT_FILTER_DISCARD, /**< Discard current event */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sync_mt_state(struct libevdev *dev, int create_events);
|
/* Keeps a record of touches during SYN_DROPPED */
|
||||||
|
enum touch_state {
|
||||||
|
TOUCH_OFF,
|
||||||
|
TOUCH_STARTED, /* Started during SYN_DROPPED */
|
||||||
|
TOUCH_STOPPED, /* Stopped during SYN_DROPPED */
|
||||||
|
TOUCH_ONGOING, /* Existed before, still have same tracking ID */
|
||||||
|
TOUCH_CHANGED, /* Existed before but have new tracking ID now, so
|
||||||
|
stopped + started in that slot */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct slot_change_state {
|
||||||
|
enum touch_state state;
|
||||||
|
unsigned long axes[NLONGS(ABS_CNT)]; /* bitmask for updated axes */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sync_mt_state(struct libevdev *dev,
|
||||||
|
struct slot_change_state changes_out[dev->num_slots]);
|
||||||
|
|
||||||
|
static int
|
||||||
|
update_key_state(struct libevdev *dev, const struct input_event *e);
|
||||||
|
|
||||||
static inline int*
|
static inline int*
|
||||||
slot_value(const struct libevdev *dev, int slot, int axis)
|
slot_value(const struct libevdev *dev, int slot, int axis)
|
||||||
|
|
@ -176,10 +180,11 @@ _libevdev_log_msg(const struct libevdev *dev,
|
||||||
|
|
||||||
if (priority > dev->log.priority)
|
if (priority > dev->log.priority)
|
||||||
return;
|
return;
|
||||||
} else if (!log_data.global_handler || priority > log_data.priority)
|
} else if (!log_data.global_handler || priority > log_data.priority) {
|
||||||
return;
|
return;
|
||||||
else if (unlikely(log_data.device_handler))
|
} else if (unlikely(log_data.device_handler)) {
|
||||||
abort(); /* Seppuku, see above */
|
abort(); /* Seppuku, see above */
|
||||||
|
}
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
if (dev && dev->log.device_handler)
|
if (dev && dev->log.device_handler)
|
||||||
|
|
@ -199,9 +204,6 @@ libevdev_reset(struct libevdev *dev)
|
||||||
free(dev->phys);
|
free(dev->phys);
|
||||||
free(dev->uniq);
|
free(dev->uniq);
|
||||||
free(dev->mt_slot_vals);
|
free(dev->mt_slot_vals);
|
||||||
free(dev->mt_sync.mt_state);
|
|
||||||
free(dev->mt_sync.tracking_id_changes);
|
|
||||||
free(dev->mt_sync.slot_update);
|
|
||||||
memset(dev, 0, sizeof(*dev));
|
memset(dev, 0, sizeof(*dev));
|
||||||
dev->fd = -1;
|
dev->fd = -1;
|
||||||
dev->initialized = false;
|
dev->initialized = false;
|
||||||
|
|
@ -299,8 +301,7 @@ _libevdev_log_priority(const struct libevdev *dev)
|
||||||
{
|
{
|
||||||
if (dev && dev->log.device_handler)
|
if (dev && dev->log.device_handler)
|
||||||
return dev->log.priority;
|
return dev->log.priority;
|
||||||
else
|
return libevdev_get_log_priority();
|
||||||
return libevdev_get_log_priority();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT int
|
LIBEVDEV_EXPORT int
|
||||||
|
|
@ -311,9 +312,65 @@ libevdev_change_fd(struct libevdev *dev, int fd)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
dev->fd = fd;
|
dev->fd = fd;
|
||||||
|
dev->grabbed = LIBEVDEV_UNGRAB;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_tracking_ids(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
if (dev->num_slots == -1 ||
|
||||||
|
!libevdev_has_event_code(dev, EV_ABS, ABS_MT_TRACKING_ID))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int slot = 0; slot < dev->num_slots; slot++)
|
||||||
|
libevdev_set_slot_value(dev, slot, ABS_MT_TRACKING_ID, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
free_slots(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
dev->num_slots = -1;
|
||||||
|
free(dev->mt_slot_vals);
|
||||||
|
dev->mt_slot_vals = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_slots(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
const struct input_absinfo *abs_info;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
free(dev->mt_slot_vals);
|
||||||
|
dev->mt_slot_vals = NULL;
|
||||||
|
|
||||||
|
/* devices with ABS_RESERVED aren't MT devices,
|
||||||
|
see the documentation for multitouch-related
|
||||||
|
functions for more details */
|
||||||
|
if (libevdev_has_event_code(dev, EV_ABS, ABS_RESERVED) ||
|
||||||
|
!libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
|
||||||
|
if (dev->num_slots != -1) {
|
||||||
|
free_slots(dev);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
abs_info = libevdev_get_abs_info(dev, ABS_MT_SLOT);
|
||||||
|
|
||||||
|
free_slots(dev);
|
||||||
|
dev->num_slots = abs_info->maximum + 1;
|
||||||
|
dev->mt_slot_vals = calloc(dev->num_slots * ABS_MT_CNT, sizeof(int));
|
||||||
|
if (!dev->mt_slot_vals) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
dev->current_slot = abs_info->value;
|
||||||
|
|
||||||
|
reset_tracking_ids(dev);
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT int
|
LIBEVDEV_EXPORT int
|
||||||
libevdev_set_fd(struct libevdev* dev, int fd)
|
libevdev_set_fd(struct libevdev* dev, int fd)
|
||||||
{
|
{
|
||||||
|
|
@ -324,8 +381,11 @@ libevdev_set_fd(struct libevdev* dev, int fd)
|
||||||
if (dev->initialized) {
|
if (dev->initialized) {
|
||||||
log_bug(dev, "device already initialized.\n");
|
log_bug(dev, "device already initialized.\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (fd < 0)
|
}
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
libevdev_reset(dev);
|
libevdev_reset(dev);
|
||||||
|
|
||||||
|
|
@ -460,41 +520,13 @@ libevdev_set_fd(struct libevdev* dev, int fd)
|
||||||
|
|
||||||
dev->fd = fd;
|
dev->fd = fd;
|
||||||
|
|
||||||
/* devices with ABS_MT_SLOT - 1 aren't MT devices,
|
rc = init_slots(dev);
|
||||||
see the documentation for multitouch-related
|
if (rc != 0)
|
||||||
functions for more details */
|
goto out;
|
||||||
if (!libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT - 1) &&
|
|
||||||
libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
|
|
||||||
const struct input_absinfo *abs_info;
|
|
||||||
|
|
||||||
abs_info = libevdev_get_abs_info(dev, ABS_MT_SLOT);
|
if (dev->num_slots != -1) {
|
||||||
|
struct slot_change_state unused[dev->num_slots];
|
||||||
dev->num_slots = abs_info->maximum + 1;
|
sync_mt_state(dev, unused);
|
||||||
dev->mt_slot_vals = calloc(dev->num_slots * ABS_MT_CNT, sizeof(int));
|
|
||||||
if (!dev->mt_slot_vals) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
dev->current_slot = abs_info->value;
|
|
||||||
|
|
||||||
dev->mt_sync.mt_state_sz = sizeof(*dev->mt_sync.mt_state) +
|
|
||||||
(dev->num_slots) * sizeof(int);
|
|
||||||
dev->mt_sync.mt_state = calloc(1, dev->mt_sync.mt_state_sz);
|
|
||||||
|
|
||||||
dev->mt_sync.tracking_id_changes_sz = NLONGS(dev->num_slots) * sizeof(long);
|
|
||||||
dev->mt_sync.tracking_id_changes = malloc(dev->mt_sync.tracking_id_changes_sz);
|
|
||||||
|
|
||||||
dev->mt_sync.slot_update_sz = NLONGS(dev->num_slots * ABS_MT_CNT) * sizeof(long);
|
|
||||||
dev->mt_sync.slot_update = malloc(dev->mt_sync.slot_update_sz);
|
|
||||||
|
|
||||||
if (!dev->mt_sync.tracking_id_changes ||
|
|
||||||
!dev->mt_sync.slot_update ||
|
|
||||||
!dev->mt_sync.mt_state) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
sync_mt_state(dev, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = init_event_queue(dev);
|
rc = init_event_queue(dev);
|
||||||
|
|
@ -521,15 +553,6 @@ libevdev_get_fd(const struct libevdev* dev)
|
||||||
return dev->fd;
|
return dev->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
init_event(struct libevdev *dev, struct input_event *ev, int type, int code, int value)
|
|
||||||
{
|
|
||||||
ev->time = dev->last_event_time;
|
|
||||||
ev->type = type;
|
|
||||||
ev->code = code;
|
|
||||||
ev->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sync_key_state(struct libevdev *dev)
|
sync_key_state(struct libevdev *dev)
|
||||||
{
|
{
|
||||||
|
|
@ -545,10 +568,8 @@ sync_key_state(struct libevdev *dev)
|
||||||
int old, new;
|
int old, new;
|
||||||
old = bit_is_set(dev->key_values, i);
|
old = bit_is_set(dev->key_values, i);
|
||||||
new = bit_is_set(keystate, i);
|
new = bit_is_set(keystate, i);
|
||||||
if (old ^ new) {
|
if (old ^ new)
|
||||||
struct input_event *ev = queue_push(dev);
|
queue_push_event(dev, EV_KEY, i, new ? 1 : 0);
|
||||||
init_event(dev, ev, EV_KEY, i, new ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dev->key_values, keystate, rc);
|
memcpy(dev->key_values, keystate, rc);
|
||||||
|
|
@ -573,10 +594,8 @@ sync_sw_state(struct libevdev *dev)
|
||||||
int old, new;
|
int old, new;
|
||||||
old = bit_is_set(dev->sw_values, i);
|
old = bit_is_set(dev->sw_values, i);
|
||||||
new = bit_is_set(swstate, i);
|
new = bit_is_set(swstate, i);
|
||||||
if (old ^ new) {
|
if (old ^ new)
|
||||||
struct input_event *ev = queue_push(dev);
|
queue_push_event(dev, EV_SW, i, new ? 1 : 0);
|
||||||
init_event(dev, ev, EV_SW, i, new ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dev->sw_values, swstate, rc);
|
memcpy(dev->sw_values, swstate, rc);
|
||||||
|
|
@ -602,8 +621,7 @@ sync_led_state(struct libevdev *dev)
|
||||||
old = bit_is_set(dev->led_values, i);
|
old = bit_is_set(dev->led_values, i);
|
||||||
new = bit_is_set(ledstate, i);
|
new = bit_is_set(ledstate, i);
|
||||||
if (old ^ new) {
|
if (old ^ new) {
|
||||||
struct input_event *ev = queue_push(dev);
|
queue_push_event(dev, EV_LED, i, new ? 1 : 0);
|
||||||
init_event(dev, ev, EV_LED, i, new ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -633,9 +651,7 @@ sync_abs_state(struct libevdev *dev)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (dev->abs_info[i].value != abs_info.value) {
|
if (dev->abs_info[i].value != abs_info.value) {
|
||||||
struct input_event *ev = queue_push(dev);
|
queue_push_event(dev, EV_ABS, i, abs_info.value);
|
||||||
|
|
||||||
init_event(dev, ev, EV_ABS, i, abs_info.value);
|
|
||||||
dev->abs_info[i].value = abs_info.value;
|
dev->abs_info[i].value = abs_info.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -646,105 +662,176 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sync_mt_state(struct libevdev *dev, int create_events)
|
sync_mt_state(struct libevdev *dev,
|
||||||
|
struct slot_change_state changes_out[dev->num_slots])
|
||||||
{
|
{
|
||||||
struct input_event *ev;
|
#define MAX_SLOTS 256
|
||||||
struct input_absinfo abs_info;
|
int rc = 0;
|
||||||
int rc;
|
struct slot_change_state changes[MAX_SLOTS] = {0};
|
||||||
int axis, slot;
|
unsigned int nslots = min(MAX_SLOTS, dev->num_slots);
|
||||||
int ioctl_success = 0;
|
|
||||||
int last_reported_slot = 0;
|
|
||||||
struct mt_sync_state *mt_state = dev->mt_sync.mt_state;
|
|
||||||
unsigned long *slot_update = dev->mt_sync.slot_update;
|
|
||||||
unsigned long *tracking_id_changes = dev->mt_sync.tracking_id_changes;
|
|
||||||
int need_tracking_id_changes = 0;
|
|
||||||
|
|
||||||
memset(dev->mt_sync.slot_update, 0, dev->mt_sync.slot_update_sz);
|
for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||||||
memset(dev->mt_sync.tracking_id_changes, 0,
|
/* EVIOCGMTSLOTS required format */
|
||||||
dev->mt_sync.tracking_id_changes_sz);
|
struct mt_sync_state {
|
||||||
|
uint32_t code;
|
||||||
|
int32_t val[MAX_SLOTS];
|
||||||
|
} mt_state;
|
||||||
|
|
||||||
#define AXISBIT(_slot, _axis) (_slot * ABS_MT_CNT + _axis - ABS_MT_MIN)
|
if (axis == ABS_MT_SLOT ||
|
||||||
|
!libevdev_has_event_code(dev, EV_ABS, axis))
|
||||||
for (axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
|
||||||
if (axis == ABS_MT_SLOT)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!libevdev_has_event_code(dev, EV_ABS, axis))
|
mt_state.code = axis;
|
||||||
continue;
|
rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(mt_state)), &mt_state);
|
||||||
|
if (rc < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
mt_state->code = axis;
|
for (unsigned int slot = 0; slot < nslots; slot++) {
|
||||||
rc = ioctl(dev->fd, EVIOCGMTSLOTS(dev->mt_sync.mt_state_sz), mt_state);
|
int val_before = *slot_value(dev, slot, axis),
|
||||||
if (rc < 0) {
|
val_after = mt_state.val[slot];
|
||||||
/* if the first ioctl fails with -EINVAL, chances are the kernel
|
|
||||||
doesn't support the ioctl. Simply continue */
|
|
||||||
if (errno == -EINVAL && !ioctl_success) {
|
|
||||||
rc = 0;
|
|
||||||
} else /* if the second, ... ioctl fails, really fail */
|
|
||||||
goto out;
|
|
||||||
} else {
|
|
||||||
if (ioctl_success == 0)
|
|
||||||
ioctl_success = 1;
|
|
||||||
|
|
||||||
for (slot = 0; slot < dev->num_slots; slot++) {
|
if (axis == ABS_MT_TRACKING_ID) {
|
||||||
|
if (val_before == -1 && val_after != -1) {
|
||||||
if (*slot_value(dev, slot, axis) == mt_state->val[slot])
|
changes[slot].state = TOUCH_STARTED;
|
||||||
continue;
|
} else if (val_before != -1 && val_after == -1) {
|
||||||
|
changes[slot].state = TOUCH_STOPPED;
|
||||||
if (axis == ABS_MT_TRACKING_ID &&
|
} else if (val_before != -1 && val_after != -1 &&
|
||||||
*slot_value(dev, slot, axis) != -1 &&
|
val_before == val_after) {
|
||||||
mt_state->val[slot] != -1) {
|
changes[slot].state = TOUCH_ONGOING;
|
||||||
set_bit(tracking_id_changes, slot);
|
} else if (val_before != -1 && val_after != -1 &&
|
||||||
need_tracking_id_changes = 1;
|
val_before != val_after) {
|
||||||
|
changes[slot].state = TOUCH_CHANGED;
|
||||||
|
} else {
|
||||||
|
changes[slot].state = TOUCH_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
*slot_value(dev, slot, axis) = mt_state->val[slot];
|
|
||||||
|
|
||||||
set_bit(slot_update, AXISBIT(slot, axis));
|
|
||||||
/* note that this slot has updates */
|
|
||||||
set_bit(slot_update, AXISBIT(slot, ABS_MT_SLOT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (val_before == val_after)
|
||||||
}
|
|
||||||
|
|
||||||
if (!create_events) {
|
|
||||||
rc = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_tracking_id_changes) {
|
|
||||||
for (slot = 0; slot < dev->num_slots; slot++) {
|
|
||||||
if (!bit_is_set(tracking_id_changes, slot))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev = queue_push(dev);
|
*slot_value(dev, slot, axis) = val_after;
|
||||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, slot);
|
|
||||||
ev = queue_push(dev);
|
|
||||||
init_event(dev, ev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
|
||||||
|
|
||||||
last_reported_slot = slot;
|
set_bit(changes[slot].axes, axis);
|
||||||
|
/* note that this slot has updates */
|
||||||
|
set_bit(changes[slot].axes, ABS_MT_SLOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
ev = queue_push(dev);
|
|
||||||
init_event(dev, ev, EV_SYN, SYN_REPORT, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (slot = 0; slot < dev->num_slots; slot++) {
|
if (dev->num_slots > MAX_SLOTS)
|
||||||
if (!bit_is_set(slot_update, AXISBIT(slot, ABS_MT_SLOT)))
|
memset(changes_out, 0, sizeof(*changes) * dev->num_slots);
|
||||||
|
|
||||||
|
memcpy(changes_out, changes, sizeof(*changes) * nslots);
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
terminate_slots(struct libevdev *dev,
|
||||||
|
const struct slot_change_state changes[dev->num_slots],
|
||||||
|
int *last_reported_slot)
|
||||||
|
{
|
||||||
|
const unsigned int map[] = {BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP,
|
||||||
|
BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP,
|
||||||
|
BTN_TOOL_QUINTTAP};
|
||||||
|
bool touches_stopped = false;
|
||||||
|
int ntouches_before = 0, ntouches_after = 0;
|
||||||
|
|
||||||
|
/* For BTN_TOOL_* emulation, we need to know how many touches we had
|
||||||
|
* before and how many we have left once we terminate all the ones
|
||||||
|
* that changed and all the ones that stopped.
|
||||||
|
*/
|
||||||
|
for (int slot = 0; slot < dev->num_slots; slot++) {
|
||||||
|
switch(changes[slot].state) {
|
||||||
|
case TOUCH_OFF:
|
||||||
|
break;
|
||||||
|
case TOUCH_CHANGED:
|
||||||
|
case TOUCH_STOPPED:
|
||||||
|
queue_push_event(dev, EV_ABS, ABS_MT_SLOT, slot);
|
||||||
|
queue_push_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
|
||||||
|
*last_reported_slot = slot;
|
||||||
|
touches_stopped = true;
|
||||||
|
ntouches_before++;
|
||||||
|
break;
|
||||||
|
case TOUCH_ONGOING:
|
||||||
|
ntouches_before++;
|
||||||
|
ntouches_after++;
|
||||||
|
break;
|
||||||
|
case TOUCH_STARTED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If any of the touches stopped, we need to split the sync state
|
||||||
|
into two frames - one with all the stopped touches, one with the
|
||||||
|
new touches starting (if any) */
|
||||||
|
if (touches_stopped) {
|
||||||
|
/* Send through the required BTN_TOOL_ 0 and 1 events for
|
||||||
|
* the previous and current number of fingers. And update
|
||||||
|
* our own key state accordingly, so that during the second
|
||||||
|
* sync event frame sync_key_state() sets everything correctly
|
||||||
|
* for the *real* number of touches.
|
||||||
|
*/
|
||||||
|
if (ntouches_before > 0 && ntouches_before <= 5) {
|
||||||
|
struct input_event ev = {
|
||||||
|
.type = EV_KEY,
|
||||||
|
.code = map[ntouches_before - 1],
|
||||||
|
.value = 0,
|
||||||
|
};
|
||||||
|
queue_push_event(dev, ev.type, ev.code, ev.value);
|
||||||
|
update_key_state(dev, &ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ntouches_after > 0 && ntouches_after <= 5) {
|
||||||
|
struct input_event ev = {
|
||||||
|
.type = EV_KEY,
|
||||||
|
.code = map[ntouches_after - 1],
|
||||||
|
.value = 1,
|
||||||
|
};
|
||||||
|
queue_push_event(dev, ev.type, ev.code, ev.value);
|
||||||
|
update_key_state(dev, &ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_push_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
push_mt_sync_events(struct libevdev *dev,
|
||||||
|
const struct slot_change_state changes[dev->num_slots],
|
||||||
|
int last_reported_slot)
|
||||||
|
{
|
||||||
|
struct input_absinfo abs_info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
for (int slot = 0; slot < dev->num_slots; slot++) {
|
||||||
|
bool have_slot_event = false;
|
||||||
|
|
||||||
|
if (!bit_is_set(changes[slot].axes, ABS_MT_SLOT))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev = queue_push(dev);
|
for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, slot);
|
|
||||||
last_reported_slot = slot;
|
|
||||||
|
|
||||||
for (axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
|
||||||
if (axis == ABS_MT_SLOT ||
|
if (axis == ABS_MT_SLOT ||
|
||||||
!libevdev_has_event_code(dev, EV_ABS, axis))
|
!libevdev_has_event_code(dev, EV_ABS, axis))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (bit_is_set(slot_update, AXISBIT(slot, axis))) {
|
if (bit_is_set(changes[slot].axes, axis)) {
|
||||||
ev = queue_push(dev);
|
/* We already sent the tracking id -1 in
|
||||||
init_event(dev, ev, EV_ABS, axis, *slot_value(dev, slot, axis));
|
* terminate_slots so don't do that again. There
|
||||||
|
* may be other axes like ABS_MT_TOOL_TYPE that
|
||||||
|
* need to be synced despite no touch being active */
|
||||||
|
if (axis == ABS_MT_TRACKING_ID &&
|
||||||
|
*slot_value(dev, slot, axis) == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!have_slot_event) {
|
||||||
|
queue_push_event(dev, EV_ABS, ABS_MT_SLOT, slot);
|
||||||
|
last_reported_slot = slot;
|
||||||
|
have_slot_event = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_push_event(dev, EV_ABS, axis,
|
||||||
|
*slot_value(dev, slot, axis));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -758,12 +845,8 @@ sync_mt_state(struct libevdev *dev, int create_events)
|
||||||
|
|
||||||
dev->current_slot = abs_info.value;
|
dev->current_slot = abs_info.value;
|
||||||
|
|
||||||
if (dev->current_slot != last_reported_slot) {
|
if (dev->current_slot != last_reported_slot)
|
||||||
ev = queue_push(dev);
|
queue_push_event(dev, EV_ABS, ABS_MT_SLOT, dev->current_slot);
|
||||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, dev->current_slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef AXISBIT
|
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
|
|
@ -783,11 +866,13 @@ read_more_events(struct libevdev *dev)
|
||||||
|
|
||||||
next = queue_next_element(dev);
|
next = queue_next_element(dev);
|
||||||
len = read(dev->fd, next, free_elem * sizeof(struct input_event));
|
len = read(dev->fd, next, free_elem * sizeof(struct input_event));
|
||||||
if (len < 0) {
|
if (len < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
} else if (len > 0 && len % sizeof(struct input_event) != 0)
|
|
||||||
|
if (len > 0 && len % sizeof(struct input_event) != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
else if (len > 0) {
|
|
||||||
|
if (len > 0) {
|
||||||
int nev = len/sizeof(struct input_event);
|
int nev = len/sizeof(struct input_event);
|
||||||
queue_set_num_elements(dev, queue_num_elements(dev) + nev);
|
queue_set_num_elements(dev, queue_num_elements(dev) + nev);
|
||||||
}
|
}
|
||||||
|
|
@ -834,12 +919,35 @@ static int
|
||||||
sync_state(struct libevdev *dev)
|
sync_state(struct libevdev *dev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct input_event *ev;
|
bool want_mt_sync = false;
|
||||||
|
int last_reported_slot = 0;
|
||||||
|
struct slot_change_state changes[dev->num_slots > 0 ? dev->num_slots : 1];
|
||||||
|
|
||||||
|
memset(changes, 0, sizeof(changes));
|
||||||
|
|
||||||
/* see section "Discarding events before synchronizing" in
|
/* see section "Discarding events before synchronizing" in
|
||||||
* libevdev/libevdev.h */
|
* libevdev/libevdev.h */
|
||||||
drain_events(dev);
|
drain_events(dev);
|
||||||
|
|
||||||
|
/* We generate one or two event frames during sync.
|
||||||
|
* The first one (if it exists) terminates all slots that have
|
||||||
|
* either terminated during SYN_DROPPED or changed their tracking
|
||||||
|
* ID.
|
||||||
|
*
|
||||||
|
* The second frame syncs everything up to the current state of the
|
||||||
|
* device - including re-starting those slots that have a changed
|
||||||
|
* tracking id.
|
||||||
|
*/
|
||||||
|
if (dev->num_slots > -1 &&
|
||||||
|
libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT)) {
|
||||||
|
want_mt_sync = true;
|
||||||
|
rc = sync_mt_state(dev, changes);
|
||||||
|
if (rc == 0)
|
||||||
|
terminate_slots(dev, changes, &last_reported_slot);
|
||||||
|
else
|
||||||
|
want_mt_sync = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (libevdev_has_event_type(dev, EV_KEY))
|
if (libevdev_has_event_type(dev, EV_KEY))
|
||||||
rc = sync_key_state(dev);
|
rc = sync_key_state(dev);
|
||||||
if (libevdev_has_event_type(dev, EV_LED))
|
if (libevdev_has_event_type(dev, EV_LED))
|
||||||
|
|
@ -848,15 +956,13 @@ sync_state(struct libevdev *dev)
|
||||||
rc = sync_sw_state(dev);
|
rc = sync_sw_state(dev);
|
||||||
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
||||||
rc = sync_abs_state(dev);
|
rc = sync_abs_state(dev);
|
||||||
if (rc == 0 && dev->num_slots > -1 &&
|
if (rc == 0 && want_mt_sync)
|
||||||
libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
push_mt_sync_events(dev, changes, last_reported_slot);
|
||||||
rc = sync_mt_state(dev, 1);
|
|
||||||
|
|
||||||
dev->queue_nsync = queue_num_elements(dev);
|
dev->queue_nsync = queue_num_elements(dev);
|
||||||
|
|
||||||
if (dev->queue_nsync > 0) {
|
if (dev->queue_nsync > 0) {
|
||||||
ev = queue_push(dev);
|
queue_push_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
init_event(dev, ev, EV_SYN, SYN_REPORT, 0);
|
|
||||||
dev->queue_nsync++;
|
dev->queue_nsync++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -890,7 +996,9 @@ update_mt_state(struct libevdev *dev, const struct input_event *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (dev->current_slot == -1)
|
}
|
||||||
|
|
||||||
|
if (dev->current_slot == -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
*slot_value(dev, dev->current_slot, e->code) = e->value;
|
*slot_value(dev, dev->current_slot, e->code) = e->value;
|
||||||
|
|
@ -966,7 +1074,8 @@ update_state(struct libevdev *dev, const struct input_event *e)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->last_event_time = e->time;
|
dev->last_event_time.tv_sec = e->input_event_sec;
|
||||||
|
dev->last_event_time.tv_usec = e->input_event_usec;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
@ -979,6 +1088,9 @@ sanitize_event(const struct libevdev *dev,
|
||||||
struct input_event *ev,
|
struct input_event *ev,
|
||||||
enum SyncState sync_state)
|
enum SyncState sync_state)
|
||||||
{
|
{
|
||||||
|
if (!libevdev_has_event_code(dev, ev->type, ev->code))
|
||||||
|
return EVENT_FILTER_DISCARD;
|
||||||
|
|
||||||
if (unlikely(dev->num_slots > -1 &&
|
if (unlikely(dev->num_slots > -1 &&
|
||||||
libevdev_event_is_code(ev, EV_ABS, ABS_MT_SLOT) &&
|
libevdev_event_is_code(ev, EV_ABS, ABS_MT_SLOT) &&
|
||||||
(ev->value < 0 || ev->value >= dev->num_slots))) {
|
(ev->value < 0 || ev->value >= dev->num_slots))) {
|
||||||
|
|
@ -992,7 +1104,9 @@ sanitize_event(const struct libevdev *dev,
|
||||||
N to -1 or from -1 to N. Never from -1 to -1, or N to M. Very
|
N to -1 or from -1 to N. Never from -1 to -1, or N to M. Very
|
||||||
unlikely to ever happen from a real device.
|
unlikely to ever happen from a real device.
|
||||||
*/
|
*/
|
||||||
} else if (unlikely(sync_state == SYNC_NONE &&
|
}
|
||||||
|
|
||||||
|
if (unlikely(sync_state == SYNC_NONE &&
|
||||||
dev->num_slots > -1 &&
|
dev->num_slots > -1 &&
|
||||||
libevdev_event_is_code(ev, EV_ABS, ABS_MT_TRACKING_ID) &&
|
libevdev_event_is_code(ev, EV_ABS, ABS_MT_TRACKING_ID) &&
|
||||||
((ev->value == -1 &&
|
((ev->value == -1 &&
|
||||||
|
|
@ -1020,7 +1134,9 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
|
||||||
if (!dev->initialized) {
|
if (!dev->initialized) {
|
||||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (dev->fd < 0)
|
}
|
||||||
|
|
||||||
|
if (dev->fd < 0)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if ((flags & valid_flags) == 0) {
|
if ((flags & valid_flags) == 0) {
|
||||||
|
|
@ -1062,8 +1178,7 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
|
||||||
read in any more.
|
read in any more.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
if (!(flags & LIBEVDEV_READ_FLAG_BLOCKING) ||
|
if (queue_num_elements(dev) == 0) {
|
||||||
queue_num_elements(dev) == 0) {
|
|
||||||
rc = read_more_events(dev);
|
rc = read_more_events(dev);
|
||||||
if (rc < 0 && rc != -EAGAIN)
|
if (rc < 0 && rc != -EAGAIN)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
@ -1095,15 +1210,8 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
|
||||||
if (flags & LIBEVDEV_READ_FLAG_SYNC && dev->queue_nsync > 0) {
|
if (flags & LIBEVDEV_READ_FLAG_SYNC && dev->queue_nsync > 0) {
|
||||||
dev->queue_nsync--;
|
dev->queue_nsync--;
|
||||||
rc = LIBEVDEV_READ_STATUS_SYNC;
|
rc = LIBEVDEV_READ_STATUS_SYNC;
|
||||||
if (dev->queue_nsync == 0) {
|
if (dev->queue_nsync == 0)
|
||||||
struct input_event next;
|
|
||||||
dev->sync_state = SYNC_NONE;
|
dev->sync_state = SYNC_NONE;
|
||||||
|
|
||||||
if (queue_peek(dev, 0, &next) == 0 &&
|
|
||||||
next.type == EV_SYN && next.code == SYN_DROPPED)
|
|
||||||
log_info(dev, "SYN_DROPPED received after finished "
|
|
||||||
"sync - you're not keeping up\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
@ -1119,7 +1227,9 @@ libevdev_has_event_pending(struct libevdev *dev)
|
||||||
if (!dev->initialized) {
|
if (!dev->initialized) {
|
||||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (dev->fd < 0)
|
}
|
||||||
|
|
||||||
|
if (dev->fd < 0)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (queue_num_elements(dev) != 0)
|
if (queue_num_elements(dev) != 0)
|
||||||
|
|
@ -1204,6 +1314,16 @@ libevdev_enable_property(struct libevdev *dev, unsigned int prop)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT int
|
||||||
|
libevdev_disable_property(struct libevdev *dev, unsigned int prop)
|
||||||
|
{
|
||||||
|
if (prop > INPUT_PROP_MAX)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
clear_bit(dev->props, prop);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT int
|
LIBEVDEV_EXPORT int
|
||||||
libevdev_has_event_type(const struct libevdev *dev, unsigned int type)
|
libevdev_has_event_type(const struct libevdev *dev, unsigned int type)
|
||||||
{
|
{
|
||||||
|
|
@ -1300,8 +1420,9 @@ libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsign
|
||||||
libevdev_has_event_code(dev, type, code)) {
|
libevdev_has_event_code(dev, type, code)) {
|
||||||
*value = libevdev_get_event_value(dev, type, code);
|
*value = libevdev_get_event_value(dev, type, code);
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
}
|
||||||
return 0;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT int
|
LIBEVDEV_EXPORT int
|
||||||
|
|
@ -1351,8 +1472,9 @@ libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigne
|
||||||
slot < (unsigned int)dev->num_slots) {
|
slot < (unsigned int)dev->num_slots) {
|
||||||
*value = libevdev_get_slot_value(dev, slot, code);
|
*value = libevdev_get_slot_value(dev, slot, code);
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
}
|
||||||
return 0;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT int
|
LIBEVDEV_EXPORT int
|
||||||
|
|
@ -1489,6 +1611,12 @@ libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
|
||||||
if (type == EV_ABS) {
|
if (type == EV_ABS) {
|
||||||
const struct input_absinfo *abs = data;
|
const struct input_absinfo *abs = data;
|
||||||
dev->abs_info[code] = *abs;
|
dev->abs_info[code] = *abs;
|
||||||
|
if (code == ABS_MT_SLOT) {
|
||||||
|
if (init_slots(dev) != 0)
|
||||||
|
return -1;
|
||||||
|
} else if (code == ABS_MT_TRACKING_ID) {
|
||||||
|
reset_tracking_ids(dev);
|
||||||
|
}
|
||||||
} else if (type == EV_REP) {
|
} else if (type == EV_REP) {
|
||||||
const int *value = data;
|
const int *value = data;
|
||||||
dev->rep_values[code] = *value;
|
dev->rep_values[code] = *value;
|
||||||
|
|
@ -1513,6 +1641,15 @@ libevdev_disable_event_code(struct libevdev *dev, unsigned int type, unsigned in
|
||||||
|
|
||||||
clear_bit(mask, code);
|
clear_bit(mask, code);
|
||||||
|
|
||||||
|
if (type == EV_ABS) {
|
||||||
|
if (code == ABS_MT_SLOT) {
|
||||||
|
if (init_slots(dev) != 0)
|
||||||
|
return -1;
|
||||||
|
} else if (code == ABS_MT_TRACKING_ID) {
|
||||||
|
reset_tracking_ids(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1524,7 +1661,9 @@ libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const stru
|
||||||
if (!dev->initialized) {
|
if (!dev->initialized) {
|
||||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (dev->fd < 0)
|
}
|
||||||
|
|
||||||
|
if (dev->fd < 0)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (code > ABS_MAX)
|
if (code > ABS_MAX)
|
||||||
|
|
@ -1547,7 +1686,9 @@ libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab)
|
||||||
if (!dev->initialized) {
|
if (!dev->initialized) {
|
||||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (dev->fd < 0)
|
}
|
||||||
|
|
||||||
|
if (dev->fd < 0)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) {
|
if (grab != LIBEVDEV_GRAB && grab != LIBEVDEV_UNGRAB) {
|
||||||
|
|
@ -1607,6 +1748,23 @@ libevdev_event_code_get_name(unsigned int type, unsigned int code)
|
||||||
return event_type_map[type][code];
|
return event_type_map[type][code];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBEVDEV_EXPORT const char *
|
||||||
|
libevdev_event_value_get_name(unsigned int type,
|
||||||
|
unsigned int code,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
/* This is a simplified version because nothing else
|
||||||
|
is an enum like ABS_MT_TOOL_TYPE so we don't need
|
||||||
|
a generic lookup */
|
||||||
|
if (type != EV_ABS || code != ABS_MT_TOOL_TYPE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (value < 0 || value > MT_TOOL_MAX)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return mt_tool_map[value];
|
||||||
|
}
|
||||||
|
|
||||||
LIBEVDEV_EXPORT const char*
|
LIBEVDEV_EXPORT const char*
|
||||||
libevdev_property_get_name(unsigned int prop)
|
libevdev_property_get_name(unsigned int prop)
|
||||||
{
|
{
|
||||||
|
|
@ -1658,7 +1816,9 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...)
|
||||||
if (!dev->initialized) {
|
if (!dev->initialized) {
|
||||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (dev->fd < 0)
|
}
|
||||||
|
|
||||||
|
if (dev->fd < 0)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
memset(ev, 0, sizeof(ev));
|
memset(ev, 0, sizeof(ev));
|
||||||
|
|
@ -1714,7 +1874,9 @@ libevdev_set_clock_id(struct libevdev *dev, int clockid)
|
||||||
if (!dev->initialized) {
|
if (!dev->initialized) {
|
||||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
} else if (dev->fd < 0)
|
}
|
||||||
|
|
||||||
|
if (dev->fd < 0)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
return ioctl(dev->fd, EVIOCSCLOCKID, &clockid) ? -errno : 0;
|
return ioctl(dev->fd, EVIOCSCLOCKID, &clockid) ? -errno : 0;
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,26 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* of this software and associated documentation files (the "Software"), to
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
* deal in the Software without restriction, including without limitation the
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
* that the name of the copyright holders not be used in advertising or
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
* publicity pertaining to distribution of the software without specific,
|
* furnished to do so, subject to the following conditions:
|
||||||
* written prior permission. The copyright holders make no representations
|
*
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
* The above copyright notice and this permission notice (including the next
|
||||||
* is" without express or implied warranty.
|
* 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.
|
||||||
*
|
*
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIBEVDEV_H
|
#ifndef LIBEVDEV_H
|
||||||
|
|
@ -39,23 +42,29 @@ extern "C" {
|
||||||
* the \ref ioctls through type-safe interfaces and provides functions to change
|
* the \ref ioctls through type-safe interfaces and provides functions to change
|
||||||
* the appearance of the device.
|
* the appearance of the device.
|
||||||
*
|
*
|
||||||
|
* Development
|
||||||
|
* ===========
|
||||||
|
* The git repository is available here:
|
||||||
|
*
|
||||||
|
* - https://gitlab.freedesktop.org/libevdev/libevdev
|
||||||
|
*
|
||||||
* Development of libevdev is discussed on
|
* Development of libevdev is discussed on
|
||||||
* [input-tools@lists.freedesktop.org](http://lists.freedesktop.org/mailman/listinfo/input-tools)
|
* [input-tools@lists.freedesktop.org](http://lists.freedesktop.org/mailman/listinfo/input-tools).
|
||||||
* Please submit patches, questions or general comments there.
|
* Please submit patches, questions or general comments there.
|
||||||
*
|
*
|
||||||
* Handling events and SYN_DROPPED
|
* Handling events and SYN_DROPPED
|
||||||
* ===============================
|
* ===============================
|
||||||
*
|
*
|
||||||
* libevdev provides an interface for handling events, including most notably
|
* libevdev provides an interface for handling events, including most notably
|
||||||
* SYN_DROPPED events. SYN_DROPPED events are sent by the kernel when the
|
* `SYN_DROPPED` events. `SYN_DROPPED` events are sent by the kernel when the
|
||||||
* process does not read events fast enough and the kernel is forced to drop
|
* process does not read events fast enough and the kernel is forced to drop
|
||||||
* some events. This causes the device to get out of sync with the process'
|
* some events. This causes the device to get out of sync with the process'
|
||||||
* view of it. libevdev handles this by telling the caller that a SYN_DROPPED
|
* view of it. libevdev handles this by telling the caller that a * `SYN_DROPPED`
|
||||||
* has been received and that the state of the device is different to what is
|
* has been received and that the state of the device is different to what is
|
||||||
* to be expected. It then provides the delta between the previous state and
|
* to be expected. It then provides the delta between the previous state and
|
||||||
* the actual state of the device as a set of events. See
|
* the actual state of the device as a set of events. See
|
||||||
* libevdev_next_event() and @ref syn_dropped for more information on how
|
* libevdev_next_event() and @ref syn_dropped for more information on how
|
||||||
* SYN_DROPPED is handled.
|
* `SYN_DROPPED` is handled.
|
||||||
*
|
*
|
||||||
* Signal safety
|
* Signal safety
|
||||||
* =============
|
* =============
|
||||||
|
|
@ -78,7 +87,7 @@ extern "C" {
|
||||||
*
|
*
|
||||||
* libevdev does not handle the file descriptors directly, it merely uses
|
* libevdev does not handle the file descriptors directly, it merely uses
|
||||||
* them. The caller is responsible for opening the file descriptors, setting
|
* them. The caller is responsible for opening the file descriptors, setting
|
||||||
* them to O_NONBLOCK and handling permissions. A caller should drain any
|
* them to `O_NONBLOCK` and handling permissions. A caller should drain any
|
||||||
* events pending on the file descriptor before passing it to libevdev.
|
* events pending on the file descriptor before passing it to libevdev.
|
||||||
*
|
*
|
||||||
* Where does libevdev sit?
|
* Where does libevdev sit?
|
||||||
|
|
@ -95,9 +104,10 @@ extern "C" {
|
||||||
*
|
*
|
||||||
* kernel → libevdev → xf86-input-evdev → X server → X client
|
* kernel → libevdev → xf86-input-evdev → X server → X client
|
||||||
*
|
*
|
||||||
* For Weston/Wayland, the stack would look like this:
|
* For anything using libinput (e.g. most Wayland compositors), the stack
|
||||||
|
* the stack would look like this:
|
||||||
*
|
*
|
||||||
* kernel → libevdev → Weston → Wayland client
|
* kernel → libevdev → libinput → Compositor → Wayland client
|
||||||
*
|
*
|
||||||
* libevdev does **not** have knowledge of X clients or Wayland clients, it is
|
* libevdev does **not** have knowledge of X clients or Wayland clients, it is
|
||||||
* too low in the stack.
|
* too low in the stack.
|
||||||
|
|
@ -135,14 +145,14 @@ extern "C" {
|
||||||
* rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
* rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
||||||
* if (rc == 0)
|
* if (rc == 0)
|
||||||
* printf("Event: %s %s %d\n",
|
* printf("Event: %s %s %d\n",
|
||||||
* libevdev_get_event_type_name(ev.type),
|
* libevdev_event_type_get_name(ev.type),
|
||||||
* libevdev_get_event_code_name(ev.type, ev.code),
|
* libevdev_event_code_get_name(ev.type, ev.code),
|
||||||
* ev.value);
|
* ev.value);
|
||||||
* } while (rc == 1 || rc == 0 || rc == -EAGAIN);
|
* } while (rc == 1 || rc == 0 || rc == -EAGAIN);
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* A more complete example is available with the libevdev-events tool here:
|
* A more complete example is available with the libevdev-events tool here:
|
||||||
* http://cgit.freedesktop.org/libevdev/tree/tools/libevdev-events.c
|
* https://gitlab.freedesktop.org/libevdev/libevdev/blob/master/tools/libevdev-events.c
|
||||||
*
|
*
|
||||||
* Backwards compatibility with older kernel
|
* Backwards compatibility with older kernel
|
||||||
* =========================================
|
* =========================================
|
||||||
|
|
@ -153,25 +163,31 @@ extern "C" {
|
||||||
* License information
|
* License information
|
||||||
* ===================
|
* ===================
|
||||||
* libevdev is licensed under the
|
* libevdev is licensed under the
|
||||||
* [X11 license](http://cgit.freedesktop.org/libevdev/tree/COPYING).
|
* [MIT license](http://cgit.freedesktop.org/libevdev/tree/COPYING).
|
||||||
|
*
|
||||||
|
* Bindings
|
||||||
|
* ===================
|
||||||
|
* - Python: https://gitlab.freedesktop.org/libevdev/python-libevdev
|
||||||
|
* - Haskell: http://hackage.haskell.org/package/evdev
|
||||||
|
* - Rust: https://crates.io/crates/evdev-rs
|
||||||
*
|
*
|
||||||
* Reporting bugs
|
* Reporting bugs
|
||||||
* ==============
|
* ==============
|
||||||
* Please report bugs in the freedesktop.org bugzilla under the libevdev product:
|
* Please report bugs in the freedesktop.org GitLab instance:
|
||||||
* https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev
|
* https://gitlab.freedesktop.org/libevdev/libevdev/issues/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @page syn_dropped SYN_DROPPED handling
|
* @page syn_dropped SYN_DROPPED handling
|
||||||
*
|
*
|
||||||
* This page describes how libevdev handles SYN_DROPPED events.
|
* This page describes how libevdev handles `SYN_DROPPED` events.
|
||||||
*
|
*
|
||||||
* Receiving SYN_DROPPED events
|
* Receiving `SYN_DROPPED` events
|
||||||
* ============================
|
* ==============================
|
||||||
*
|
*
|
||||||
* The kernel sends evdev events separated by an event of type EV_SYN and
|
* The kernel sends evdev events separated by an event of type `EV_SYN` and
|
||||||
* code SYN_REPORT. Such an event marks the end of a frame of hardware
|
* code `SYN_REPORT`. Such an event marks the end of a frame of hardware
|
||||||
* events. The number of events between SYN_REPORT events is arbitrary and
|
* events. The number of events between `SYN_REPORT` events is arbitrary and
|
||||||
* depends on the hardware. An example event sequence may look like this:
|
* depends on the hardware. An example event sequence may look like this:
|
||||||
* @code
|
* @code
|
||||||
* EV_ABS ABS_X 9
|
* EV_ABS ABS_X 9
|
||||||
|
|
@ -191,7 +207,7 @@ extern "C" {
|
||||||
* the buffer size to handle at least one full event. In the normal case,
|
* the buffer size to handle at least one full event. In the normal case,
|
||||||
* the client reads the event and the kernel can place the next event in the
|
* the client reads the event and the kernel can place the next event in the
|
||||||
* buffer. If the client is not fast enough, the kernel places an event of
|
* buffer. If the client is not fast enough, the kernel places an event of
|
||||||
* type EV_SYN and code SYN_DROPPED into the buffer, effectively notifying
|
* type `EV_SYN` and code `SYN_DROPPED` into the buffer, effectively notifying
|
||||||
* the client that some events were lost. The above example event sequence
|
* the client that some events were lost. The above example event sequence
|
||||||
* may look like this (note the missing/repeated events):
|
* may look like this (note the missing/repeated events):
|
||||||
* @code
|
* @code
|
||||||
|
|
@ -210,19 +226,19 @@ extern "C" {
|
||||||
* EV_SYN SYN_REPORT 0
|
* EV_SYN SYN_REPORT 0
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* A SYN_DROPPED event may be recieved at any time in the event sequence.
|
* A `SYN_DROPPED` event may be recieved at any time in the event sequence.
|
||||||
* When a SYN_DROPPED event is received, the client must:
|
* When a `SYN_DROPPED` event is received, the client must:
|
||||||
* * discard all events since the last SYN_REPORT
|
* * discard all events since the last `SYN_REPORT`
|
||||||
* * discard all events until including the next SYN_REPORT
|
* * discard all events until including the next `SYN_REPORT`
|
||||||
* These event are part of incomplete event frames.
|
* These event are part of incomplete event frames.
|
||||||
*
|
*
|
||||||
* Synchronizing the state of the device
|
* Synchronizing the state of the device
|
||||||
* =====================================
|
* =====================================
|
||||||
*
|
*
|
||||||
* The handling of the device after a SYN_DROPPED depends on the available
|
* The handling of the device after a `SYN_DROPPED` depends on the available
|
||||||
* event codes. For all event codes of type EV_REL, no handling is
|
* event codes. For all event codes of type `EV_REL`, no handling is
|
||||||
* necessary, there is no state attached. For all event codes of type
|
* necessary, there is no state attached. For all event codes of type
|
||||||
* EV_KEY, EV_SW, EV_LED and EV_SND, the matching @ref ioctls retrieve the
|
* `EV_KEY`, `EV_SW`, `EV_LED` and `EV_SND`, the matching @ref ioctls retrieve the
|
||||||
* current state. The caller must then compare the last-known state to the
|
* current state. The caller must then compare the last-known state to the
|
||||||
* retrieved state and handle the deltas accordingly.
|
* retrieved state and handle the deltas accordingly.
|
||||||
* libevdev simplifies this approach: if the state of the device has
|
* libevdev simplifies this approach: if the state of the device has
|
||||||
|
|
@ -230,12 +246,12 @@ extern "C" {
|
||||||
* passes it to the caller during libevdev_next_event() if
|
* passes it to the caller during libevdev_next_event() if
|
||||||
* @ref LIBEVDEV_READ_FLAG_SYNC is set.
|
* @ref LIBEVDEV_READ_FLAG_SYNC is set.
|
||||||
*
|
*
|
||||||
* For events of type EV_ABS and an event code less than ABS_MT_SLOT, the
|
* For events of type `EV_ABS` and an event code less than `ABS_MT_SLOT`, the
|
||||||
* handling of state changes is as described above. For events between
|
* handling of state changes is as described above. For events between
|
||||||
* ABS_MT_SLOT and ABS_MAX, the event handling differs.
|
* `ABS_MT_SLOT` and `ABS_MAX`, the event handling differs.
|
||||||
* Slots are the vehicles to transport information for multiple simultaneous
|
* Slots are the vehicles to transport information for multiple simultaneous
|
||||||
* touchpoints on a device. Slots are re-used once a touchpoint has ended.
|
* touchpoints on a device. Slots are re-used once a touchpoint has ended.
|
||||||
* The kernel sends an ABS_MT_SLOT event whenever the current slot
|
* The kernel sends an `ABS_MT_SLOT` event whenever the current slot
|
||||||
* changes; any event in the above axis range applies only to the currently
|
* changes; any event in the above axis range applies only to the currently
|
||||||
* active slot.
|
* active slot.
|
||||||
* Thus, an event sequence from a slot-capable device may look like this:
|
* Thus, an event sequence from a slot-capable device may look like this:
|
||||||
|
|
@ -246,24 +262,24 @@ extern "C" {
|
||||||
* EV_ABS ABS_MT_POSITION_Y 80
|
* EV_ABS ABS_MT_POSITION_Y 80
|
||||||
* EV_SYN SYN_REPORT 0
|
* EV_SYN SYN_REPORT 0
|
||||||
* @endcode
|
* @endcode
|
||||||
* Note the lack of ABS_MT_SLOT: the first ABS_MT_POSITION_Y applies to
|
* Note the lack of `ABS_MT_SLOT`: the first `ABS_MT_POSITION_Y` applies to
|
||||||
* a slot opened previously, and is the only axis that changed for that
|
* a slot opened previously, and is the only axis that changed for that
|
||||||
* slot. The touchpoint in slot 1 now has position 100/80.
|
* slot. The touchpoint in slot 1 now has position `100/80`.
|
||||||
* The kernel does not provide events if a value does not change, and does
|
* The kernel does not provide events if a value does not change, and does
|
||||||
* not send ABS_MT_SLOT events if the slot does not change, or none of the
|
* not send `ABS_MT_SLOT` events if the slot does not change, or none of the
|
||||||
* values within a slot changes. A client must thus keep the state for each
|
* values within a slot changes. A client must thus keep the state for each
|
||||||
* slot.
|
* slot.
|
||||||
*
|
*
|
||||||
* If a SYN_DROPPED is received, the client must sync all slots
|
* If a `SYN_DROPPED` is received, the client must sync all slots
|
||||||
* individually and update its internal state. libevdev simplifies this by
|
* individually and update its internal state. libevdev simplifies this by
|
||||||
* generating multiple events:
|
* generating multiple events:
|
||||||
* * for each slot on the device, libevdev generates an
|
* * for each slot on the device, libevdev generates an
|
||||||
* ABS_MT_SLOT event with the value set to the slot number
|
* `ABS_MT_SLOT` event with the value set to the slot number
|
||||||
* * for each event code between ABS_MT_SLOT + 1 and ABS_MAX that changed
|
* * for each event code between `ABS_MT_SLOT + 1` and `ABS_MAX` that changed
|
||||||
* state for this slot, libevdev generates an event for the new state
|
* state for this slot, libevdev generates an event for the new state
|
||||||
* * libevdev sends a final ABS_MT_SLOT event for the current slot as
|
* * libevdev sends a final `ABS_MT_SLOT` event for the current slot as
|
||||||
* seen by the kernel
|
* seen by the kernel
|
||||||
* * libevdev terminates this sequence with an EV_SYN SYN_REPORT event
|
* * libevdev terminates this sequence with an `EV_SYN SYN_REPORT` event
|
||||||
*
|
*
|
||||||
* An example event sequence for such a sync may look like this:
|
* An example event sequence for such a sync may look like this:
|
||||||
* @code
|
* @code
|
||||||
|
|
@ -278,26 +294,26 @@ extern "C" {
|
||||||
* EV_ABS ABS_MT_SLOT 1
|
* EV_ABS ABS_MT_SLOT 1
|
||||||
* EV_SYN SYN_REPORT 0
|
* EV_SYN SYN_REPORT 0
|
||||||
* @endcode
|
* @endcode
|
||||||
* Note the terminating ABS_MT_SLOT event, this indicates that the kernel
|
* Note the terminating `ABS_MT_SLOT` event, this indicates that the kernel
|
||||||
* currently has slot 1 active.
|
* currently has slot 1 active.
|
||||||
*
|
*
|
||||||
* Synchronizing ABS_MT_TRACKING_ID
|
* Synchronizing ABS_MT_TRACKING_ID
|
||||||
* ================================
|
* ================================
|
||||||
*
|
*
|
||||||
* The event code ABS_MT_TRACKING_ID is used to denote the start and end of
|
* The event code `ABS_MT_TRACKING_ID` is used to denote the start and end of
|
||||||
* a touch point within a slot. An ABS_MT_TRACKING_ID of zero or greater
|
* a touch point within a slot. An `ABS_MT_TRACKING_ID` of zero or greater
|
||||||
* denotes the start of a touchpoint, an ABS_MT_TRACKING_ID of -1 denotes
|
* denotes the start of a touchpoint, an `ABS_MT_TRACKING_ID` of -1 denotes
|
||||||
* the end of a touchpoint within this slot. During SYN_DROPPED, a touch
|
* the end of a touchpoint within this slot. During `SYN_DROPPED`, a touch
|
||||||
* point may have ended and re-started within a slot - a client must check
|
* point may have ended and re-started within a slot - a client must check
|
||||||
* the ABS_MT_TRACKING_ID. libevdev simplifies this by emulating extra
|
* the `ABS_MT_TRACKING_ID`. libevdev simplifies this by emulating extra
|
||||||
* events if the ABS_MT_TRACKING_ID has changed:
|
* events if the `ABS_MT_TRACKING_ID` has changed:
|
||||||
* * if the ABS_MT_TRACKING_ID was valid and is -1, libevdev enqueues an
|
* * if the `ABS_MT_TRACKING_ID` was valid and is -1, libevdev enqueues an
|
||||||
* ABS_MT_TRACKING_ID event with value -1.
|
* `ABS_MT_TRACKING_ID` event with value -1.
|
||||||
* * if the ABS_MT_TRACKING_ID was -1 and is now a valid ID, libevdev
|
* * if the `ABS_MT_TRACKING_ID` was -1 and is now a valid ID, libevdev
|
||||||
* enqueues an ABS_MT_TRACKING_ID event with the current value.
|
* enqueues an `ABS_MT_TRACKING_ID` event with the current value.
|
||||||
* * if the ABS_MT_TRACKING_ID was a valid ID and is now a different valid
|
* * if the `ABS_MT_TRACKING_ID` was a valid ID and is now a different valid
|
||||||
* ID, libevev enqueues an ABS_MT_TRACKING_ID event with value -1 and
|
* ID, libevev enqueues an `ABS_MT_TRACKING_ID` event with value -1 and
|
||||||
* another ABS_MT_TRACKING_ID event with the new value.
|
* another `ABS_MT_TRACKING_ID` event with the new value.
|
||||||
*
|
*
|
||||||
* An example event sequence for such a sync may look like this:
|
* An example event sequence for such a sync may look like this:
|
||||||
* @code
|
* @code
|
||||||
|
|
@ -318,14 +334,14 @@ extern "C" {
|
||||||
* EV_SYN SYN_REPORT 0
|
* EV_SYN SYN_REPORT 0
|
||||||
* @endcode
|
* @endcode
|
||||||
* Note how the touchpoint in slot 0 was terminated, the touchpoint in slot
|
* Note how the touchpoint in slot 0 was terminated, the touchpoint in slot
|
||||||
* 2 was terminated and then started with a new ABS_MT_TRACKING_ID. The touchpoint
|
* 2 was terminated and then started with a new `ABS_MT_TRACKING_ID`. The touchpoint
|
||||||
* in slot 1 maintained the same ABS_MT_TRACKING_ID and only updated the
|
* in slot 1 maintained the same `ABS_MT_TRACKING_ID` and only updated the
|
||||||
* coordinates. Slot 1 is the currently active slot.
|
* coordinates. Slot 1 is the currently active slot.
|
||||||
*
|
*
|
||||||
* In the case of a SYN_DROPPED event, a touch point may be invisible to a
|
* In the case of a `SYN_DROPPED` event, a touch point may be invisible to a
|
||||||
* client if it started after SYN_DROPPED and finished before the client
|
* client if it started after `SYN_DROPPED` and finished before the client
|
||||||
* handles events again. The below example shows an example event sequence
|
* handles events again. The below example shows an example event sequence
|
||||||
* and what libevdev sees in the case of a SYN_DROPPED event:
|
* and what libevdev sees in the case of a `SYN_DROPPED` event:
|
||||||
* @code
|
* @code
|
||||||
*
|
*
|
||||||
* kernel | userspace
|
* kernel | userspace
|
||||||
|
|
@ -349,7 +365,7 @@ extern "C" {
|
||||||
* @endcode
|
* @endcode
|
||||||
* If such an event sequence occurs, libevdev will send all updated axes
|
* If such an event sequence occurs, libevdev will send all updated axes
|
||||||
* during the sync process. Axis events may thus be generated for devices
|
* during the sync process. Axis events may thus be generated for devices
|
||||||
* without a currently valid ABS_MT_TRACKING_ID. Specifically for the above
|
* without a currently valid `ABS_MT_TRACKING_ID`. Specifically for the above
|
||||||
* example, the client would receive the following event sequence:
|
* example, the client would receive the following event sequence:
|
||||||
* @code
|
* @code
|
||||||
* EV_ABS ABS_MT_SLOT 0 ← LIBEVDEV_READ_FLAG_NORMAL
|
* EV_ABS ABS_MT_SLOT 0 ← LIBEVDEV_READ_FLAG_NORMAL
|
||||||
|
|
@ -375,15 +391,15 @@ extern "C" {
|
||||||
* Discarding events before synchronizing
|
* Discarding events before synchronizing
|
||||||
* =====================================
|
* =====================================
|
||||||
*
|
*
|
||||||
* The kernel implements the client buffer as a ring buffer. SYN_DROPPED
|
* The kernel implements the client buffer as a ring buffer. `SYN_DROPPED`
|
||||||
* events are handled when the buffer is full and a new event is received
|
* events are handled when the buffer is full and a new event is received
|
||||||
* from a device. All existing events are discarded, a SYN_DROPPED is added
|
* from a device. All existing events are discarded, a `SYN_DROPPED` is added
|
||||||
* to the buffer followed by the actual device event. Further events will be
|
* to the buffer followed by the actual device event. Further events will be
|
||||||
* appended to the buffer until it is either read by the client, or filled
|
* appended to the buffer until it is either read by the client, or filled
|
||||||
* again, at which point the sequence repeats.
|
* again, at which point the sequence repeats.
|
||||||
*
|
*
|
||||||
* When the client reads the buffer, the buffer will thus always consist of
|
* When the client reads the buffer, the buffer will thus always consist of
|
||||||
* exactly one SYN_DROPPED event followed by an unspecified number of real
|
* exactly one `SYN_DROPPED` event followed by an unspecified number of real
|
||||||
* events. The data the ioctls return is the current state of the device,
|
* events. The data the ioctls return is the current state of the device,
|
||||||
* i.e. the state after all these events have been processed. For example,
|
* i.e. the state after all these events have been processed. For example,
|
||||||
* assume the buffer contains the following sequence:
|
* assume the buffer contains the following sequence:
|
||||||
|
|
@ -405,10 +421,10 @@ extern "C" {
|
||||||
* @endcode
|
* @endcode
|
||||||
* An ioctl at any time in this sequence will return a value of 6 for ABS_X.
|
* An ioctl at any time in this sequence will return a value of 6 for ABS_X.
|
||||||
*
|
*
|
||||||
* libevdev discards all events after a SYN_DROPPED to ensure the events
|
* libevdev discards all events after a `SYN_DROPPED` to ensure the events
|
||||||
* during @ref LIBEVDEV_READ_FLAG_SYNC represent the last known state of the
|
* during @ref LIBEVDEV_READ_FLAG_SYNC represent the last known state of the
|
||||||
* device. This loses some granularity of the events especially as the time
|
* device. This loses some granularity of the events especially as the time
|
||||||
* between the SYN_DROPPED and the sync process increases. It does however
|
* between the `SYN_DROPPED` and the sync process increases. It does however
|
||||||
* avoid spurious cursor movements. In the above example, the event sequence
|
* avoid spurious cursor movements. In the above example, the event sequence
|
||||||
* by libevdev is:
|
* by libevdev is:
|
||||||
* @code
|
* @code
|
||||||
|
|
@ -433,7 +449,7 @@ extern "C" {
|
||||||
* Minimum requirements
|
* Minimum requirements
|
||||||
* ====================
|
* ====================
|
||||||
* libevdev requires a 2.6.36 kernel as minimum. Specifically, it requires
|
* libevdev requires a 2.6.36 kernel as minimum. Specifically, it requires
|
||||||
* kernel-support for ABS_MT_SLOT.
|
* kernel-support for `ABS_MT_SLOT`.
|
||||||
*
|
*
|
||||||
* Event and input property names
|
* Event and input property names
|
||||||
* ==============================
|
* ==============================
|
||||||
|
|
@ -442,28 +458,28 @@ extern "C" {
|
||||||
* The list of event names is compiled at build-time, any events not defined
|
* The list of event names is compiled at build-time, any events not defined
|
||||||
* at build time will not resolve. Specifically,
|
* at build time will not resolve. Specifically,
|
||||||
* libevdev_event_code_get_name() for an undefined type or code will
|
* libevdev_event_code_get_name() for an undefined type or code will
|
||||||
* always return NULL. Likewise, libevdev_property_get_name() will return NULL
|
* always return `NULL`. Likewise, libevdev_property_get_name() will return NULL
|
||||||
* for properties undefined at build-time.
|
* for properties undefined at build-time.
|
||||||
*
|
*
|
||||||
* Input properties
|
* Input properties
|
||||||
* ================
|
* ================
|
||||||
* If the kernel does not support input properties, specifically the
|
* If the kernel does not support input properties, specifically the
|
||||||
* EVIOCGPROPS ioctl, libevdev does not expose input properties to the caller.
|
* `EVIOCGPROPS` ioctl, libevdev does not expose input properties to the caller.
|
||||||
* Specifically, libevdev_has_property() will always return 0 unless the
|
* Specifically, libevdev_has_property() will always return 0 unless the
|
||||||
* property has been manually set with libevdev_enable_property().
|
* property has been manually set with libevdev_enable_property().
|
||||||
*
|
*
|
||||||
* This also applies to the libevdev-uinput code. If uinput does not honor
|
* This also applies to the libevdev-uinput code. If uinput does not honor
|
||||||
* UI_SET_PROPBIT, libevdev will continue without setting the properties on
|
* `UI_SET_PROPBIT`, libevdev will continue without setting the properties on
|
||||||
* the device.
|
* the device.
|
||||||
*
|
*
|
||||||
* MT slot behavior
|
* MT slot behavior
|
||||||
* =================
|
* =================
|
||||||
* If the kernel does not support the EVIOCGMTSLOTS ioctl, libevdev
|
* If the kernel does not support the `EVIOCGMTSLOTS` ioctl, libevdev
|
||||||
* assumes all values in all slots are 0 and continues without an error.
|
* assumes all values in all slots are 0 and continues without an error.
|
||||||
*
|
*
|
||||||
* SYN_DROPPED behavior
|
* SYN_DROPPED behavior
|
||||||
* ====================
|
* ====================
|
||||||
* A kernel without SYN_DROPPED won't send such an event. libevdev_next_event()
|
* A kernel without `SYN_DROPPED` won't send such an event. libevdev_next_event()
|
||||||
* will never require the switch to sync mode.
|
* will never require the switch to sync mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -484,11 +500,11 @@ extern "C" {
|
||||||
* <dd>supported, see libevdev_enable_event_code()</dd>
|
* <dd>supported, see libevdev_enable_event_code()</dd>
|
||||||
* <dt>EVIOCGKEYCODE:</dt>
|
* <dt>EVIOCGKEYCODE:</dt>
|
||||||
* <dd>currently not supported</dd>
|
* <dd>currently not supported</dd>
|
||||||
* <dt>EVIOCGKEYCODE:</dt>
|
|
||||||
* <dd>currently not supported</dd>
|
|
||||||
* <dt>EVIOCSKEYCODE:</dt>
|
* <dt>EVIOCSKEYCODE:</dt>
|
||||||
* <dd>currently not supported</dd>
|
* <dd>currently not supported</dd>
|
||||||
* <dt>EVIOCSKEYCODE:</dt>
|
* <dt>EVIOCGKEYCODE_V2:</dt>
|
||||||
|
* <dd>currently not supported</dd>
|
||||||
|
* <dt>EVIOCSKEYCODE_V2:</dt>
|
||||||
* <dd>currently not supported</dd>
|
* <dd>currently not supported</dd>
|
||||||
* <dt>EVIOCGNAME:</dt>
|
* <dt>EVIOCGNAME:</dt>
|
||||||
* <dd>supported, see libevdev_get_name()</dd>
|
* <dd>supported, see libevdev_get_name()</dd>
|
||||||
|
|
@ -528,6 +544,10 @@ extern "C" {
|
||||||
* <dt>EVIOCREVOKE:</dt>
|
* <dt>EVIOCREVOKE:</dt>
|
||||||
* <dd>currently not supported, see
|
* <dd>currently not supported, see
|
||||||
* http://lists.freedesktop.org/archives/input-tools/2014-January/000688.html</dd>
|
* http://lists.freedesktop.org/archives/input-tools/2014-January/000688.html</dd>
|
||||||
|
* <dt>EVIOCGMASK:</dt>
|
||||||
|
* <dd>currently not supported</dd>
|
||||||
|
* <dt>EVIOCSMASK:</dt>
|
||||||
|
* <dd>currently not supported</dd>
|
||||||
* </dl>
|
* </dl>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
@ -562,7 +582,7 @@ extern "C" {
|
||||||
* [Check unit testing framework](http://check.sourceforge.net/). Tests are
|
* [Check unit testing framework](http://check.sourceforge.net/). Tests are
|
||||||
* divided into test suites and test cases. Most tests create a uinput device,
|
* divided into test suites and test cases. Most tests create a uinput device,
|
||||||
* so you'll need to run as root, and your kernel must have
|
* so you'll need to run as root, and your kernel must have
|
||||||
* CONFIG_INPUT_UINPUT enabled.
|
* `CONFIG_INPUT_UINPUT` enabled.
|
||||||
*
|
*
|
||||||
* To run a specific suite only:
|
* To run a specific suite only:
|
||||||
*
|
*
|
||||||
|
|
@ -618,7 +638,7 @@ extern "C" {
|
||||||
* return ENOMEM;
|
* return ENOMEM;
|
||||||
*
|
*
|
||||||
* err = libevdev_set_fd(dev, fd);
|
* err = libevdev_set_fd(dev, fd);
|
||||||
* if (err < 0) {
|
* if (err < 0)
|
||||||
* printf("Failed (errno %d): %s\n", -err, strerror(-err));
|
* printf("Failed (errno %d): %s\n", -err, strerror(-err));
|
||||||
*
|
*
|
||||||
* libevdev_free(dev);
|
* libevdev_free(dev);
|
||||||
|
|
@ -655,9 +675,9 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* @defgroup bits Querying device capabilities
|
* @defgroup bits Querying device capabilities
|
||||||
*
|
*
|
||||||
* Abstraction functions to handle device capabilities, specificially
|
* Abstraction functions to handle device capabilities, specifically
|
||||||
* device properties such as the name of the device and the bits
|
* device properties such as the name of the device and the bits
|
||||||
* representing the events suppported by this device.
|
* representing the events supported by this device.
|
||||||
*
|
*
|
||||||
* The logical state returned may lag behind the physical state of the device.
|
* The logical state returned may lag behind the physical state of the device.
|
||||||
* libevdev queries the device state on libevdev_set_fd() and then relies on
|
* libevdev queries the device state on libevdev_set_fd() and then relies on
|
||||||
|
|
@ -669,11 +689,11 @@ extern "C" {
|
||||||
/**
|
/**
|
||||||
* @defgroup mt Multi-touch related functions
|
* @defgroup mt Multi-touch related functions
|
||||||
* Functions for querying multi-touch-related capabilities. MT devices
|
* Functions for querying multi-touch-related capabilities. MT devices
|
||||||
* following the kernel protocol B (using ABS_MT_SLOT) provide multiple touch
|
* following the kernel protocol B (using `ABS_MT_SLOT`) provide multiple touch
|
||||||
* points through so-called slots on the same axis. The slots are enumerated,
|
* points through so-called slots on the same axis. The slots are enumerated,
|
||||||
* a client reading from the device will first get an ABS_MT_SLOT event, then
|
* a client reading from the device will first get an ABS_MT_SLOT event, then
|
||||||
* the values of axes changed in this slot. Multiple slots may be provided in
|
* the values of axes changed in this slot. Multiple slots may be provided in
|
||||||
* before an EV_SYN event.
|
* before an `EV_SYN` event.
|
||||||
*
|
*
|
||||||
* As with @ref bits, the logical state of the device as seen by the library
|
* As with @ref bits, the logical state of the device as seen by the library
|
||||||
* depends on the caller using libevdev_next_event().
|
* depends on the caller using libevdev_next_event().
|
||||||
|
|
@ -681,17 +701,17 @@ extern "C" {
|
||||||
* The Linux kernel requires all axes on a device to have a semantic
|
* The Linux kernel requires all axes on a device to have a semantic
|
||||||
* meaning, matching the axis names in linux/input.h. Some devices merely
|
* meaning, matching the axis names in linux/input.h. Some devices merely
|
||||||
* export a number of axes beyond the available axis list. For those
|
* export a number of axes beyond the available axis list. For those
|
||||||
* devices, the multitouch information is invalid. Specfically, if a device
|
* devices, the multitouch information is invalid. Specifically, if a device
|
||||||
* provides the ABS_MT_SLOT axis AND also the (ABS_MT_SLOT - 1) axis, the
|
* provides the `ABS_MT_SLOT` axis AND also the `ABS_RESERVED` axis, the
|
||||||
* device is not treated as multitouch device. No slot information is
|
* device is not treated as multitouch device. No slot information is
|
||||||
* available and the ABS_MT axis range for these devices is treated as all
|
* available and the `ABS_MT` axis range for these devices is treated as all
|
||||||
* other EV_ABS axes.
|
* other `EV_ABS` axes.
|
||||||
*
|
*
|
||||||
* Note that because of limitations in the kernel API, such fake multitouch
|
* Note that because of limitations in the kernel API, such fake multitouch
|
||||||
* devices can not be reliably synched after a SYN_DROPPED event. libevdev
|
* devices can not be reliably synced after a `SYN_DROPPED` event. libevdev
|
||||||
* ignores all ABS_MT axis values during the sync process and instead
|
* ignores all `ABS_MT` axis values during the sync process and instead
|
||||||
* relies on the device to send the current axis value with the first event
|
* relies on the device to send the current axis value with the first event
|
||||||
* after SYN_DROPPED.
|
* after `SYN_DROPPED`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -796,7 +816,7 @@ int libevdev_new_from_fd(int fd, struct libevdev **dev);
|
||||||
* libevdev</code> is invalid and must not be used.
|
* libevdev</code> is invalid and must not be used.
|
||||||
*
|
*
|
||||||
* Note that calling libevdev_free() does not close the file descriptor
|
* Note that calling libevdev_free() does not close the file descriptor
|
||||||
* currently asssociated with this instance.
|
* currently associated with this instance.
|
||||||
*
|
*
|
||||||
* @param dev The evdev device
|
* @param dev The evdev device
|
||||||
*
|
*
|
||||||
|
|
@ -956,10 +976,14 @@ enum libevdev_grab_mode {
|
||||||
* Grabbing an already grabbed device, or ungrabbing an ungrabbed device is
|
* Grabbing an already grabbed device, or ungrabbing an ungrabbed device is
|
||||||
* a noop and always succeeds.
|
* a noop and always succeeds.
|
||||||
*
|
*
|
||||||
|
* A grab is an operation tied to a file descriptor, not a device. If a
|
||||||
|
* client changes the file descriptor with libevdev_change_fd(), it must
|
||||||
|
* also re-issue a grab with libevdev_grab().
|
||||||
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param grab If true, grab the device. Otherwise ungrab the device.
|
* @param grab If true, grab the device. Otherwise ungrab the device.
|
||||||
*
|
*
|
||||||
* @return 0 if the device was successfull grabbed or ungrabbed, or a
|
* @return 0 if the device was successfully grabbed or ungrabbed, or a
|
||||||
* negative errno in case of failure.
|
* negative errno in case of failure.
|
||||||
*/
|
*/
|
||||||
int libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab);
|
int libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab);
|
||||||
|
|
@ -985,7 +1009,7 @@ int libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab);
|
||||||
* events like EV_REL.
|
* events like EV_REL.
|
||||||
*
|
*
|
||||||
* Unless otherwise specified, libevdev function behavior is undefined until
|
* Unless otherwise specified, libevdev function behavior is undefined until
|
||||||
* a successfull call to libevdev_set_fd().
|
* a successful call to libevdev_set_fd().
|
||||||
*
|
*
|
||||||
* @param dev The evdev device
|
* @param dev The evdev device
|
||||||
* @param fd The file descriptor for the device
|
* @param fd The file descriptor for the device
|
||||||
|
|
@ -1024,6 +1048,9 @@ int libevdev_set_fd(struct libevdev* dev, int fd);
|
||||||
*
|
*
|
||||||
* The fd may be open in O_RDONLY or O_RDWR.
|
* The fd may be open in O_RDONLY or O_RDWR.
|
||||||
*
|
*
|
||||||
|
* After changing the fd, the device is assumed ungrabbed and a caller must
|
||||||
|
* call libevdev_grab() again.
|
||||||
|
*
|
||||||
* It is an error to call this function before calling libevdev_set_fd().
|
* It is an error to call this function before calling libevdev_set_fd().
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
|
|
@ -1254,7 +1281,9 @@ int libevdev_get_id_product(const struct libevdev *dev);
|
||||||
* @param product_id The product ID to assign to this device
|
* @param product_id The product ID to assign to this device
|
||||||
*
|
*
|
||||||
* @note This function may be called before libevdev_set_fd(). A call to
|
* @note This function may be called before libevdev_set_fd(). A call to
|
||||||
* libevdev_set_fd() will overwrite any previously set value.
|
* libevdev_set_fd() will overwrite any previously set value. Even though
|
||||||
|
* the function accepts an int for product_id the value is truncated at 16
|
||||||
|
* bits.
|
||||||
*/
|
*/
|
||||||
void libevdev_set_id_product(struct libevdev *dev, int product_id);
|
void libevdev_set_id_product(struct libevdev *dev, int product_id);
|
||||||
|
|
||||||
|
|
@ -1276,7 +1305,9 @@ int libevdev_get_id_vendor(const struct libevdev *dev);
|
||||||
* @param vendor_id The vendor ID to assign to this device
|
* @param vendor_id The vendor ID to assign to this device
|
||||||
*
|
*
|
||||||
* @note This function may be called before libevdev_set_fd(). A call to
|
* @note This function may be called before libevdev_set_fd(). A call to
|
||||||
* libevdev_set_fd() will overwrite any previously set value.
|
* libevdev_set_fd() will overwrite any previously set value. Even though
|
||||||
|
* the function accepts an int for vendor_id the value is truncated at 16
|
||||||
|
* bits.
|
||||||
*/
|
*/
|
||||||
void libevdev_set_id_vendor(struct libevdev *dev, int vendor_id);
|
void libevdev_set_id_vendor(struct libevdev *dev, int vendor_id);
|
||||||
|
|
||||||
|
|
@ -1298,7 +1329,9 @@ int libevdev_get_id_bustype(const struct libevdev *dev);
|
||||||
* @param bustype The bustype to assign to this device
|
* @param bustype The bustype to assign to this device
|
||||||
*
|
*
|
||||||
* @note This function may be called before libevdev_set_fd(). A call to
|
* @note This function may be called before libevdev_set_fd(). A call to
|
||||||
* libevdev_set_fd() will overwrite any previously set value.
|
* libevdev_set_fd() will overwrite any previously set value. Even though
|
||||||
|
* the function accepts an int for bustype the value is truncated at 16
|
||||||
|
* bits.
|
||||||
*/
|
*/
|
||||||
void libevdev_set_id_bustype(struct libevdev *dev, int bustype);
|
void libevdev_set_id_bustype(struct libevdev *dev, int bustype);
|
||||||
|
|
||||||
|
|
@ -1320,7 +1353,9 @@ int libevdev_get_id_version(const struct libevdev *dev);
|
||||||
* @param version The version to assign to this device
|
* @param version The version to assign to this device
|
||||||
*
|
*
|
||||||
* @note This function may be called before libevdev_set_fd(). A call to
|
* @note This function may be called before libevdev_set_fd(). A call to
|
||||||
* libevdev_set_fd() will overwrite any previously set value.
|
* libevdev_set_fd() will overwrite any previously set value. Even though
|
||||||
|
* the function accepts an int for version the value is truncated at 16
|
||||||
|
* bits.
|
||||||
*/
|
*/
|
||||||
void libevdev_set_id_version(struct libevdev *dev, int version);
|
void libevdev_set_id_version(struct libevdev *dev, int version);
|
||||||
|
|
||||||
|
|
@ -1360,6 +1395,16 @@ int libevdev_has_property(const struct libevdev *dev, unsigned int prop);
|
||||||
*/
|
*/
|
||||||
int libevdev_enable_property(struct libevdev *dev, unsigned int prop);
|
int libevdev_enable_property(struct libevdev *dev, unsigned int prop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup kernel
|
||||||
|
*
|
||||||
|
* @param dev The evdev device
|
||||||
|
* @param prop The input property to disable, one of INPUT_PROP_...
|
||||||
|
*
|
||||||
|
* @return 0 on success or -1 on failure
|
||||||
|
*/
|
||||||
|
int libevdev_disable_property(struct libevdev *dev, unsigned int prop);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup bits
|
* @ingroup bits
|
||||||
*
|
*
|
||||||
|
|
@ -1477,8 +1522,7 @@ const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, un
|
||||||
* the event.
|
* the event.
|
||||||
*
|
*
|
||||||
* If the device supports ABS_MT_SLOT, the value returned for any ABS_MT_*
|
* If the device supports ABS_MT_SLOT, the value returned for any ABS_MT_*
|
||||||
* event code is the value of the currently active slot. You should use
|
* event code is undefined. Use libevdev_get_slot_value() instead.
|
||||||
* libevdev_get_slot_value() instead.
|
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param type The event type for the code to query (EV_SYN, EV_REL, etc.)
|
* @param type The event type for the code to query (EV_SYN, EV_REL, etc.)
|
||||||
|
|
@ -1518,9 +1562,11 @@ int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsi
|
||||||
* @param value The new value to set
|
* @param value The new value to set
|
||||||
*
|
*
|
||||||
* @return 0 on success, or -1 on failure.
|
* @return 0 on success, or -1 on failure.
|
||||||
* @retval -1 the device does not have the event type or code enabled, or the code is outside the
|
* @retval -1
|
||||||
* allowed limits for the given type, or the type cannot be set, or the
|
* - the device does not have the event type or code enabled, or
|
||||||
* value is not permitted for the given code.
|
* - the code is outside the allowed limits for the given type, or
|
||||||
|
* - the type cannot be set, or
|
||||||
|
* - the value is not permitted for the given code.
|
||||||
*
|
*
|
||||||
* @see libevdev_set_slot_value
|
* @see libevdev_set_slot_value
|
||||||
* @see libevdev_get_event_value
|
* @see libevdev_get_event_value
|
||||||
|
|
@ -1595,9 +1641,11 @@ int libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsig
|
||||||
* @param value The new value to set
|
* @param value The new value to set
|
||||||
*
|
*
|
||||||
* @return 0 on success, or -1 on failure.
|
* @return 0 on success, or -1 on failure.
|
||||||
* @retval -1 the device does not have the event code enabled, or the code is
|
* @retval -1
|
||||||
* outside the allowed limits for multitouch events, or the slot number is outside
|
* - the device does not have the event code enabled, or
|
||||||
* the limits for this device, or the device does not support multitouch events.
|
* - the code is outside the allowed limits for multitouch events, or
|
||||||
|
* - the slot number is outside the limits for this device, or
|
||||||
|
* - the device does not support multitouch events.
|
||||||
*
|
*
|
||||||
* @see libevdev_set_event_value
|
* @see libevdev_set_event_value
|
||||||
* @see libevdev_get_slot_value
|
* @see libevdev_get_slot_value
|
||||||
|
|
@ -1672,9 +1720,9 @@ int libevdev_get_current_slot(const struct libevdev *dev);
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param code One of ABS_X, ABS_Y, ...
|
* @param code One of ABS_X, ABS_Y, ...
|
||||||
* @param min The new minimum for this axis
|
* @param val The new minimum for this axis
|
||||||
*/
|
*/
|
||||||
void libevdev_set_abs_minimum(struct libevdev *dev, unsigned int code, int min);
|
void libevdev_set_abs_minimum(struct libevdev *dev, unsigned int code, int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup kernel
|
* @ingroup kernel
|
||||||
|
|
@ -1685,9 +1733,9 @@ void libevdev_set_abs_minimum(struct libevdev *dev, unsigned int code, int min);
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param code One of ABS_X, ABS_Y, ...
|
* @param code One of ABS_X, ABS_Y, ...
|
||||||
* @param max The new maxium for this axis
|
* @param val The new maxium for this axis
|
||||||
*/
|
*/
|
||||||
void libevdev_set_abs_maximum(struct libevdev *dev, unsigned int code, int max);
|
void libevdev_set_abs_maximum(struct libevdev *dev, unsigned int code, int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup kernel
|
* @ingroup kernel
|
||||||
|
|
@ -1698,9 +1746,9 @@ void libevdev_set_abs_maximum(struct libevdev *dev, unsigned int code, int max);
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param code One of ABS_X, ABS_Y, ...
|
* @param code One of ABS_X, ABS_Y, ...
|
||||||
* @param fuzz The new fuzz for this axis
|
* @param val The new fuzz for this axis
|
||||||
*/
|
*/
|
||||||
void libevdev_set_abs_fuzz(struct libevdev *dev, unsigned int code, int fuzz);
|
void libevdev_set_abs_fuzz(struct libevdev *dev, unsigned int code, int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup kernel
|
* @ingroup kernel
|
||||||
|
|
@ -1711,9 +1759,9 @@ void libevdev_set_abs_fuzz(struct libevdev *dev, unsigned int code, int fuzz);
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param code One of ABS_X, ABS_Y, ...
|
* @param code One of ABS_X, ABS_Y, ...
|
||||||
* @param flat The new flat for this axis
|
* @param val The new flat for this axis
|
||||||
*/
|
*/
|
||||||
void libevdev_set_abs_flat(struct libevdev *dev, unsigned int code, int flat);
|
void libevdev_set_abs_flat(struct libevdev *dev, unsigned int code, int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup kernel
|
* @ingroup kernel
|
||||||
|
|
@ -1724,9 +1772,9 @@ void libevdev_set_abs_flat(struct libevdev *dev, unsigned int code, int flat);
|
||||||
*
|
*
|
||||||
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
* @param dev The evdev device, already initialized with libevdev_set_fd()
|
||||||
* @param code One of ABS_X, ABS_Y, ...
|
* @param code One of ABS_X, ABS_Y, ...
|
||||||
* @param resolution The new axis resolution
|
* @param val The new axis resolution
|
||||||
*/
|
*/
|
||||||
void libevdev_set_abs_resolution(struct libevdev *dev, unsigned int code, int resolution);
|
void libevdev_set_abs_resolution(struct libevdev *dev, unsigned int code, int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup kernel
|
* @ingroup kernel
|
||||||
|
|
@ -2006,6 +2054,29 @@ const char * libevdev_event_type_get_name(unsigned int type);
|
||||||
*/
|
*/
|
||||||
const char * libevdev_event_code_get_name(unsigned int type, unsigned int code);
|
const char * libevdev_event_code_get_name(unsigned int type, unsigned int code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* This function resolves the event value for a code.
|
||||||
|
*
|
||||||
|
* For almost all event codes this will return NULL as the value is just a
|
||||||
|
* numerical value. As of kernel 4.17, the only event code that will return
|
||||||
|
* a non-NULL value is EV_ABS/ABS_MT_TOOL_TYPE.
|
||||||
|
*
|
||||||
|
* @param type The event type for the value to query (EV_ABS, etc.)
|
||||||
|
* @param code The event code for the value to query (e.g. ABS_MT_TOOL_TYPE)
|
||||||
|
* @param value The event value to return the name for (e.g. MT_TOOL_PALM)
|
||||||
|
*
|
||||||
|
* @return The name of the given event value (e.g. MT_TOOL_PALM) or NULL for
|
||||||
|
* an invalid type or code or NULL for an axis that has numerical values
|
||||||
|
* only.
|
||||||
|
*
|
||||||
|
* @note The list of names is compiled into libevdev. If the kernel adds new
|
||||||
|
* defines for new event values, libevdev will not automatically pick these up.
|
||||||
|
*/
|
||||||
|
const char * libevdev_event_value_get_name(unsigned int type,
|
||||||
|
unsigned int code,
|
||||||
|
int value);
|
||||||
/**
|
/**
|
||||||
* @ingroup misc
|
* @ingroup misc
|
||||||
*
|
*
|
||||||
|
|
@ -2114,6 +2185,136 @@ int libevdev_event_code_from_name(unsigned int type, const char *name);
|
||||||
int libevdev_event_code_from_name_n(unsigned int type, const char *name,
|
int libevdev_event_code_from_name_n(unsigned int type, const char *name,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* Look up an event value by its type, code and name. Event values start
|
||||||
|
* with a fixed prefix followed by their name (eg., "MT_TOOL_PALM"). The
|
||||||
|
* prefix must be included in the name. It returns the constant assigned
|
||||||
|
* to the event code or -1 if not found.
|
||||||
|
*
|
||||||
|
* You have to pass the event type and code where to look for the name. For
|
||||||
|
* instance, to resolve "MT_TOOL_PALM" you need to pass EV_ABS as type,
|
||||||
|
* ABS_MT_TOOL_TYPE as code and "MT_TOOL_PALM" as string.
|
||||||
|
*
|
||||||
|
* As of kernel 4.17, only EV_ABS/ABS_MT_TOOL_TYPE support name resolution.
|
||||||
|
*
|
||||||
|
* @param type The event type (EV_* constant) where to look for the name.
|
||||||
|
* @param code The event code (ABS_* constant) where to look for the name.
|
||||||
|
* @param name A non-NULL string describing an input-event value
|
||||||
|
* ("MT_TOOL_TYPE", ...)
|
||||||
|
*
|
||||||
|
* @return The given value constant for the name or -1 if not found.
|
||||||
|
*/
|
||||||
|
int libevdev_event_value_from_name(unsigned int type, unsigned int code,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* Look up an event type for a event code name. For example, the name
|
||||||
|
* "ABS_Y" returns EV_ABS. For the lookup to succeed, the name must be
|
||||||
|
* unique, which is the case for all defines as of kernel 5.0 and likely to
|
||||||
|
* be the case in the future.
|
||||||
|
*
|
||||||
|
* This is equivalent to libevdev_event_type_from_name() but takes the code
|
||||||
|
* name instead of the type name.
|
||||||
|
*
|
||||||
|
* @param name A non-NULL string describing an input-event value
|
||||||
|
* ("ABS_X", "REL_Y", "KEY_A", ...)
|
||||||
|
*
|
||||||
|
* @return The given event code for the name or -1 if not found.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
libevdev_event_type_from_code_name(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* Look up an event type for a event code name. For example, the name
|
||||||
|
* "ABS_Y" returns EV_ABS. For the lookup to succeed, the name must be
|
||||||
|
* unique, which is the case for all defines as of kernel 5.0 and likely to
|
||||||
|
* be the case in the future.
|
||||||
|
*
|
||||||
|
* This is equivalent to libevdev_event_type_from_name_n() but takes the code
|
||||||
|
* name instead of the type name.
|
||||||
|
*
|
||||||
|
* @param name A non-NULL string describing an input-event value
|
||||||
|
* ("ABS_X", "REL_Y", "KEY_A", ...)
|
||||||
|
* @param len The length of the passed string excluding any terminating 0
|
||||||
|
* character.
|
||||||
|
*
|
||||||
|
* @return The given event code for the name or -1 if not found.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
libevdev_event_type_from_code_name_n(const char *name, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* Look up an event code by its name. For example, the name "ABS_Y"
|
||||||
|
* returns 1. For the lookup to succeed, the name must be unique, which is
|
||||||
|
* the case for all defines as of kernel 5.0 and likely to be the case in
|
||||||
|
* the future.
|
||||||
|
*
|
||||||
|
* This is equivalent to libevdev_event_code_from_name() without the need
|
||||||
|
* for knowing the event type.
|
||||||
|
*
|
||||||
|
* @param name A non-NULL string describing an input-event value
|
||||||
|
* ("ABS_X", "REL_Y", "KEY_A", ...)
|
||||||
|
*
|
||||||
|
* @return The given event code for the name or -1 if not found.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
libevdev_event_code_from_code_name(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* Look up an event code by its name. For example, the name "ABS_Y"
|
||||||
|
* returns 1. For the lookup to succeed, the name must be unique, which is
|
||||||
|
* the case for all defines as of kernel 5.0 and likely to be the case in
|
||||||
|
* the future.
|
||||||
|
*
|
||||||
|
* This is equivalent to libevdev_event_code_from_name_n() without the need
|
||||||
|
* for knowing the event type.
|
||||||
|
*
|
||||||
|
* @param name A non-NULL string describing an input-event value
|
||||||
|
* ("ABS_X", "REL_Y", "KEY_A", ...)
|
||||||
|
* @param len The length of the passed string excluding any terminating 0
|
||||||
|
* character.
|
||||||
|
*
|
||||||
|
* @return The given event code for the name or -1 if not found.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
libevdev_event_code_from_code_name_n(const char *name, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup misc
|
||||||
|
*
|
||||||
|
* Look up an event value by its type, code and name. Event values start
|
||||||
|
* with a fixed prefix followed by their name (eg., "MT_TOOL_PALM"). The
|
||||||
|
* prefix must be included in the name. It returns the constant assigned
|
||||||
|
* to the event code or -1 if not found.
|
||||||
|
*
|
||||||
|
* You have to pass the event type and code where to look for the name. For
|
||||||
|
* instance, to resolve "MT_TOOL_PALM" you need to pass EV_ABS as type,
|
||||||
|
* ABS_MT_TOOL_TYPE as code and "MT_TOOL_PALM" as string.
|
||||||
|
*
|
||||||
|
* As of kernel 4.17, only EV_ABS/ABS_MT_TOOL_TYPE support name resolution.
|
||||||
|
*
|
||||||
|
* @param type The event type (EV_* constant) where to look for the name.
|
||||||
|
* @param code The event code (ABS_* constant) where to look for the name.
|
||||||
|
* @param name A non-NULL string describing an input-event value
|
||||||
|
* ("MT_TOOL_TYPE", ...)
|
||||||
|
* @param len The length of the string in @p name excluding any terminating 0
|
||||||
|
* character.
|
||||||
|
*
|
||||||
|
* @return The given value constant for the name or -1 if not found.
|
||||||
|
*/
|
||||||
|
int libevdev_event_value_from_name_n(unsigned int type, unsigned int code,
|
||||||
|
const char *name, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup misc
|
* @ingroup misc
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,6 @@
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
|
* Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LIBEVDEV_1 {
|
LIBEVDEV_1 {
|
||||||
|
|
@ -112,3 +95,29 @@ global:
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
} LIBEVDEV_1;
|
} LIBEVDEV_1;
|
||||||
|
|
||||||
|
LIBEVDEV_1_6 {
|
||||||
|
global:
|
||||||
|
libevdev_event_value_get_name;
|
||||||
|
libevdev_event_value_from_name;
|
||||||
|
libevdev_event_value_from_name_n;
|
||||||
|
local:
|
||||||
|
*;
|
||||||
|
} LIBEVDEV_1_3;
|
||||||
|
|
||||||
|
LIBEVDEV_1_7 {
|
||||||
|
global:
|
||||||
|
libevdev_event_code_from_code_name;
|
||||||
|
libevdev_event_code_from_code_name_n;
|
||||||
|
libevdev_event_type_from_code_name;
|
||||||
|
libevdev_event_type_from_code_name_n;
|
||||||
|
local:
|
||||||
|
*;
|
||||||
|
} LIBEVDEV_1_6;
|
||||||
|
|
||||||
|
LIBEVDEV_1_10 {
|
||||||
|
global:
|
||||||
|
libevdev_disable_property;
|
||||||
|
local:
|
||||||
|
*;
|
||||||
|
} LIBEVDEV_1_7;
|
||||||
|
|
|
||||||
|
|
@ -1,213 +1,231 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
# Parses linux/input.h scanning for #define KEY_FOO 134
|
# Parses linux/input.h scanning for #define KEY_FOO 134
|
||||||
# Prints C header files or Python files that can be used as
|
# Prints C header files or Python files that can be used as
|
||||||
# mapping and lookup tables.
|
# mapping and lookup tables.
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class Bits(object):
|
class Bits(object):
|
||||||
pass
|
def __init__(self):
|
||||||
|
self.max_codes = {}
|
||||||
|
|
||||||
|
|
||||||
prefixes = [
|
prefixes = [
|
||||||
"EV_",
|
"EV_",
|
||||||
"REL_",
|
"REL_",
|
||||||
"ABS_",
|
"ABS_",
|
||||||
"KEY_",
|
"KEY_",
|
||||||
"BTN_",
|
"BTN_",
|
||||||
"LED_",
|
"LED_",
|
||||||
"SND_",
|
"SND_",
|
||||||
"MSC_",
|
"MSC_",
|
||||||
"SW_",
|
"SW_",
|
||||||
"FF_",
|
"FF_",
|
||||||
"SYN_",
|
"SYN_",
|
||||||
"REP_",
|
"REP_",
|
||||||
"INPUT_PROP_",
|
"INPUT_PROP_",
|
||||||
|
"MT_TOOL_",
|
||||||
]
|
]
|
||||||
|
|
||||||
blacklist = [
|
duplicates = [
|
||||||
"EV_VERSION",
|
"EV_VERSION",
|
||||||
"BTN_MISC",
|
"BTN_MISC",
|
||||||
"BTN_MOUSE",
|
"BTN_MOUSE",
|
||||||
"BTN_JOYSTICK",
|
"BTN_JOYSTICK",
|
||||||
"BTN_GAMEPAD",
|
"BTN_GAMEPAD",
|
||||||
"BTN_DIGI",
|
"BTN_DIGI",
|
||||||
"BTN_WHEEL",
|
"BTN_WHEEL",
|
||||||
"BTN_TRIGGER_HAPPY"
|
"BTN_TRIGGER_HAPPY",
|
||||||
|
"SW_MAX",
|
||||||
|
"REP_MAX",
|
||||||
]
|
]
|
||||||
|
|
||||||
btn_additional = [
|
btn_additional = [
|
||||||
[0, "BTN_A"],
|
[0, "BTN_A"],
|
||||||
[0, "BTN_B"],
|
[0, "BTN_B"],
|
||||||
[0, "BTN_X"],
|
[0, "BTN_X"],
|
||||||
[0, "BTN_Y"],
|
[0, "BTN_Y"],
|
||||||
]
|
]
|
||||||
|
|
||||||
names = [
|
code_prefixes = [
|
||||||
"REL_",
|
"REL_",
|
||||||
"ABS_",
|
"ABS_",
|
||||||
"KEY_",
|
"KEY_",
|
||||||
"BTN_",
|
"BTN_",
|
||||||
"LED_",
|
"LED_",
|
||||||
"SND_",
|
"SND_",
|
||||||
"MSC_",
|
"MSC_",
|
||||||
"SW_",
|
"SW_",
|
||||||
"FF_",
|
"FF_",
|
||||||
"SYN_",
|
"SYN_",
|
||||||
"REP_",
|
"REP_",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def print_bits(bits, prefix):
|
def print_bits(bits, prefix):
|
||||||
if not hasattr(bits, prefix):
|
if not hasattr(bits, prefix):
|
||||||
return
|
return
|
||||||
print("static const char * const %s_map[%s_MAX + 1] = {" % (prefix, prefix.upper()))
|
print("static const char * const %s_map[%s_MAX + 1] = {" % (prefix, prefix.upper()))
|
||||||
for val, name in list(getattr(bits, prefix).items()):
|
for val, name in sorted(list(getattr(bits, prefix).items())):
|
||||||
print(" [%s] = \"%s\"," % (name, name))
|
print(" [%s] = \"%s\"," % (name, name))
|
||||||
if prefix == "key":
|
if prefix == "key":
|
||||||
for val, name in list(getattr(bits, "btn").items()):
|
for val, name in sorted(list(getattr(bits, "btn").items())):
|
||||||
print(" [%s] = \"%s\"," % (name, name))
|
print(" [%s] = \"%s\"," % (name, name))
|
||||||
print("};")
|
print("};")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
|
|
||||||
def print_map(bits):
|
def print_map(bits):
|
||||||
print("static const char * const * const event_type_map[EV_MAX + 1] = {")
|
print("static const char * const * const event_type_map[EV_MAX + 1] = {")
|
||||||
|
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
if prefix == "BTN_" or prefix == "EV_" or prefix == "INPUT_PROP_":
|
if prefix in ["BTN_", "EV_", "INPUT_PROP_", "MT_TOOL_"]:
|
||||||
continue
|
continue
|
||||||
print(" [EV_%s] = %s_map," % (prefix[:-1], prefix[:-1].lower()))
|
print(" [EV_%s] = %s_map," % (prefix[:-1], prefix[:-1].lower()))
|
||||||
|
|
||||||
print("};")
|
print("};")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
print("#if __clang__")
|
print("#if __clang__")
|
||||||
print("#pragma clang diagnostic push")
|
print("#pragma clang diagnostic push")
|
||||||
print("#pragma clang diagnostic ignored \"-Winitializer-overrides\"")
|
print("#pragma clang diagnostic ignored \"-Winitializer-overrides\"")
|
||||||
print("#else")
|
print("#elif __GNUC__")
|
||||||
print("#pragma GCC diagnostic push")
|
print("#pragma GCC diagnostic push")
|
||||||
print("#pragma GCC diagnostic ignored \"-Woverride-init\"")
|
print("#pragma GCC diagnostic ignored \"-Woverride-init\"")
|
||||||
print("#endif")
|
print("#endif")
|
||||||
print("static const int ev_max[EV_MAX + 1] = {")
|
print("static const int ev_max[EV_MAX + 1] = {")
|
||||||
print(" [0 ... EV_MAX] = -1,")
|
for val in range(bits.max_codes["EV_MAX"] + 1):
|
||||||
for prefix in prefixes:
|
if val in bits.ev:
|
||||||
if prefix == "BTN_" or prefix == "EV_" or prefix == "INPUT_PROP_":
|
prefix = bits.ev[val][3:]
|
||||||
continue
|
if prefix + "_" in prefixes:
|
||||||
print(" [EV_%s] = %s_MAX," % (prefix[:-1], prefix[:-1]))
|
print(" %s_MAX," % prefix)
|
||||||
print("};")
|
continue
|
||||||
print("#if __clang__")
|
print(" -1,")
|
||||||
print("#pragma clang diagnostic pop /* \"-Winitializer-overrides\" */")
|
print("};")
|
||||||
print("#else")
|
print("#if __clang__")
|
||||||
print("#pragma GCC diagnostic pop /* \"-Woverride-init\" */")
|
print("#pragma clang diagnostic pop /* \"-Winitializer-overrides\" */")
|
||||||
print("#endif");
|
print("#elif __GNUC__")
|
||||||
print("")
|
print("#pragma GCC diagnostic pop /* \"-Woverride-init\" */")
|
||||||
|
print("#endif")
|
||||||
|
print("")
|
||||||
|
|
||||||
def print_python_map(bits):
|
|
||||||
print("map = {")
|
|
||||||
|
|
||||||
for val, name in list(getattr(bits, "ev").items()):
|
|
||||||
name = name[3:]
|
|
||||||
if name == "REP" or name == "PWR" or name == "FF_STATUS" or name == "MAX":
|
|
||||||
continue
|
|
||||||
print(" %d : %s_map," % (val, name.lower()))
|
|
||||||
|
|
||||||
print("}")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
def print_lookup(bits, prefix):
|
def print_lookup(bits, prefix):
|
||||||
if not hasattr(bits, prefix):
|
if not hasattr(bits, prefix):
|
||||||
return
|
return
|
||||||
|
|
||||||
names = list(getattr(bits, prefix).items())
|
names = sorted(list(getattr(bits, prefix).items()))
|
||||||
if prefix == "btn":
|
if prefix == "btn":
|
||||||
names = names + btn_additional;
|
names = names + btn_additional
|
||||||
|
|
||||||
|
# We need to manually add the _MAX codes because some are
|
||||||
|
# duplicates
|
||||||
|
maxname = "%s_MAX" % (prefix.upper())
|
||||||
|
if maxname in duplicates:
|
||||||
|
names.append((bits.max_codes[maxname], maxname))
|
||||||
|
|
||||||
|
for val, name in sorted(names, key=lambda e: e[1]):
|
||||||
|
print(" { .name = \"%s\", .value = %s }," % (name, name))
|
||||||
|
|
||||||
for val, name in sorted(names, key=lambda e: e[1]):
|
|
||||||
print(" { .name = \"%s\", .value = %s }," % (name, name))
|
|
||||||
|
|
||||||
def print_lookup_table(bits):
|
def print_lookup_table(bits):
|
||||||
print("struct name_entry {")
|
print("struct name_entry {")
|
||||||
print(" const char *name;")
|
print(" const char *name;")
|
||||||
print(" unsigned int value;")
|
print(" unsigned int value;")
|
||||||
print("};")
|
print("};")
|
||||||
print("")
|
print("")
|
||||||
print("static const struct name_entry ev_names[] = {")
|
print("static const struct name_entry tool_type_names[] = {")
|
||||||
print_lookup(bits, "ev")
|
print_lookup(bits, "mt_tool")
|
||||||
print("};")
|
print("};")
|
||||||
print("")
|
print("")
|
||||||
|
print("static const struct name_entry ev_names[] = {")
|
||||||
|
print_lookup(bits, "ev")
|
||||||
|
print("};")
|
||||||
|
print("")
|
||||||
|
|
||||||
|
print("static const struct name_entry code_names[] = {")
|
||||||
|
for prefix in sorted(code_prefixes, key=lambda e: e):
|
||||||
|
print_lookup(bits, prefix[:-1].lower())
|
||||||
|
print("};")
|
||||||
|
print("")
|
||||||
|
print("static const struct name_entry prop_names[] = {")
|
||||||
|
print_lookup(bits, "input_prop")
|
||||||
|
print("};")
|
||||||
|
print("")
|
||||||
|
|
||||||
print("static const struct name_entry code_names[] = {")
|
|
||||||
for prefix in sorted(names, key=lambda e: e):
|
|
||||||
print_lookup(bits, prefix[:-1].lower())
|
|
||||||
print("};")
|
|
||||||
print("")
|
|
||||||
print("static const struct name_entry prop_names[] = {")
|
|
||||||
print_lookup(bits, "input_prop")
|
|
||||||
print("};")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
def print_mapping_table(bits):
|
def print_mapping_table(bits):
|
||||||
print("/* THIS FILE IS GENERATED, DO NOT EDIT */")
|
print("/* THIS FILE IS GENERATED, DO NOT EDIT */")
|
||||||
print("")
|
print("")
|
||||||
print("#ifndef EVENT_NAMES_H")
|
print("#ifndef EVENT_NAMES_H")
|
||||||
print("#define EVENT_NAMES_H")
|
print("#define EVENT_NAMES_H")
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
if prefix == "BTN_":
|
if prefix == "BTN_":
|
||||||
continue
|
continue
|
||||||
print_bits(bits, prefix[:-1].lower())
|
print_bits(bits, prefix[:-1].lower())
|
||||||
|
|
||||||
print_map(bits)
|
print_map(bits)
|
||||||
print_lookup_table(bits)
|
print_lookup_table(bits)
|
||||||
|
|
||||||
|
print("#endif /* EVENT_NAMES_H */")
|
||||||
|
|
||||||
print("#endif /* EVENT_NAMES_H */")
|
|
||||||
|
|
||||||
def parse_define(bits, line):
|
def parse_define(bits, line):
|
||||||
m = re.match(r"^#define\s+(\w+)\s+(\w+)", line)
|
m = re.match(r"^#define\s+(\w+)\s+(\w+)", line)
|
||||||
if m == None:
|
if m is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
name = m.group(1)
|
name = m.group(1)
|
||||||
|
|
||||||
if name in blacklist:
|
try:
|
||||||
return
|
value = int(m.group(2), 0)
|
||||||
|
except ValueError:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
for prefix in prefixes:
|
||||||
value = int(m.group(2), 0)
|
if not name.startswith(prefix):
|
||||||
except ValueError:
|
continue
|
||||||
return
|
|
||||||
|
|
||||||
for prefix in prefixes:
|
if name.endswith("_MAX"):
|
||||||
if not name.startswith(prefix):
|
bits.max_codes[name] = value
|
||||||
continue
|
|
||||||
|
|
||||||
attrname = prefix[:-1].lower()
|
if name in duplicates:
|
||||||
|
return
|
||||||
|
|
||||||
if not hasattr(bits, attrname):
|
attrname = prefix[:-1].lower()
|
||||||
setattr(bits, attrname, {})
|
|
||||||
b = getattr(bits, attrname)
|
|
||||||
b[value] = name
|
|
||||||
|
|
||||||
def parse(fp):
|
if not hasattr(bits, attrname):
|
||||||
bits = Bits()
|
setattr(bits, attrname, {})
|
||||||
|
b = getattr(bits, attrname)
|
||||||
|
b[value] = name
|
||||||
|
|
||||||
lines = fp.readlines()
|
|
||||||
for line in lines:
|
|
||||||
if not line.startswith("#define"):
|
|
||||||
continue
|
|
||||||
parse_define(bits, line)
|
|
||||||
|
|
||||||
return bits
|
def parse(lines):
|
||||||
|
bits = Bits()
|
||||||
|
for line in lines:
|
||||||
|
if not line.startswith("#define"):
|
||||||
|
continue
|
||||||
|
parse_define(bits, line)
|
||||||
|
|
||||||
|
return bits
|
||||||
|
|
||||||
|
|
||||||
def usage(prog):
|
def usage(prog):
|
||||||
print("Usage: cat <files> | %s" % prog)
|
print("Usage: %s <files>".format(prog))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 1:
|
if len(sys.argv) <= 1:
|
||||||
usage(sys.argv[0])
|
usage(sys.argv[0])
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
bits = parse(sys.stdin)
|
from itertools import chain
|
||||||
print_mapping_table(bits)
|
lines = chain(*[open(f).readlines() for f in sys.argv[1:]])
|
||||||
|
bits = parse(lines)
|
||||||
|
print_mapping_table(bits)
|
||||||
|
|
|
||||||
299
meson.build
Normal file
299
meson.build
Normal file
|
|
@ -0,0 +1,299 @@
|
||||||
|
project('libevdev', 'c',
|
||||||
|
version: '1.13.6', # change autotools version too
|
||||||
|
license: 'MIT/Expat',
|
||||||
|
default_options: [ 'c_std=gnu99', 'warning_level=2' ],
|
||||||
|
meson_version: '>= 0.56.0')
|
||||||
|
|
||||||
|
libevdev_version = meson.project_version().split('.')
|
||||||
|
|
||||||
|
dir_root = meson.project_source_root()
|
||||||
|
dir_src = dir_root / 'libevdev'
|
||||||
|
dir_src_test = dir_root / 'test'
|
||||||
|
|
||||||
|
# Include directories
|
||||||
|
includes_include = include_directories('include')
|
||||||
|
|
||||||
|
# DO NOT MODIFY THIS
|
||||||
|
# Use symbol versioning instead.
|
||||||
|
libevdev_lt_c=5
|
||||||
|
libevdev_lt_r=0
|
||||||
|
libevdev_lt_a=3
|
||||||
|
|
||||||
|
# convert to soname
|
||||||
|
libevdev_so_version = '@0@.@1@.@2@'.format((libevdev_lt_c - libevdev_lt_a),
|
||||||
|
libevdev_lt_a, libevdev_lt_r)
|
||||||
|
|
||||||
|
|
||||||
|
# Compiler setup
|
||||||
|
cc = meson.get_compiler('c')
|
||||||
|
cppflags = ['-Wno-unused-parameter', '-fvisibility=hidden']
|
||||||
|
cflags = cppflags + ['-Wmissing-prototypes', '-Wstrict-prototypes']
|
||||||
|
add_project_arguments(cflags, language: 'c')
|
||||||
|
add_project_arguments(cppflags, language: 'cpp')
|
||||||
|
|
||||||
|
# config.h
|
||||||
|
config_h = configuration_data()
|
||||||
|
config_h.set('_GNU_SOURCE', '1')
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
pkgconfig = import('pkgconfig')
|
||||||
|
dep_lm = cc.find_library('m')
|
||||||
|
dep_rt = cc.find_library('rt')
|
||||||
|
|
||||||
|
input_h = dir_root / 'include' / 'linux' / host_machine.system() / 'input.h'
|
||||||
|
input_event_codes_h = dir_root / 'include' / 'linux' / host_machine.system() / 'input-event-codes.h'
|
||||||
|
|
||||||
|
# event-names.h
|
||||||
|
make_event_names = find_program('libevdev/make-event-names.py')
|
||||||
|
event_names_h = configure_file(input: 'libevdev/libevdev.h',
|
||||||
|
output: 'event-names.h',
|
||||||
|
command: [make_event_names, input_h, input_event_codes_h],
|
||||||
|
capture: true)
|
||||||
|
|
||||||
|
|
||||||
|
# libevdev.so
|
||||||
|
install_headers('libevdev/libevdev.h',
|
||||||
|
'libevdev/libevdev-uinput.h',
|
||||||
|
subdir: 'libevdev-1.0/libevdev')
|
||||||
|
src_libevdev = [event_names_h] + files(
|
||||||
|
'libevdev/libevdev.h',
|
||||||
|
'libevdev/libevdev-int.h',
|
||||||
|
'libevdev/libevdev-util.h',
|
||||||
|
'libevdev/libevdev-uinput.c',
|
||||||
|
'libevdev/libevdev-uinput.h',
|
||||||
|
'libevdev/libevdev-uinput-int.h',
|
||||||
|
'libevdev/libevdev.c',
|
||||||
|
'libevdev/libevdev-names.c',
|
||||||
|
'include/linux/input.h',
|
||||||
|
'include/linux/uinput.h',
|
||||||
|
)
|
||||||
|
|
||||||
|
mapfile = dir_src / 'libevdev.sym'
|
||||||
|
version_flag = '-Wl,--version-script,@0@'.format(mapfile)
|
||||||
|
lib_libevdev = library('evdev',
|
||||||
|
src_libevdev,
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_rt],
|
||||||
|
version: libevdev_so_version,
|
||||||
|
link_args: version_flag,
|
||||||
|
link_depends: mapfile,
|
||||||
|
install: true
|
||||||
|
)
|
||||||
|
|
||||||
|
inc_libevdev = include_directories('.')
|
||||||
|
dep_libevdev = declare_dependency(link_with: lib_libevdev,
|
||||||
|
include_directories: [inc_libevdev])
|
||||||
|
|
||||||
|
pkgconfig.generate(
|
||||||
|
filebase: 'libevdev',
|
||||||
|
name: 'libevdev',
|
||||||
|
description: 'Handler library for evdev events',
|
||||||
|
version: meson.project_version(),
|
||||||
|
libraries: lib_libevdev,
|
||||||
|
subdirs: 'libevdev-1.0',
|
||||||
|
)
|
||||||
|
|
||||||
|
man_config = configuration_data()
|
||||||
|
man_config.set('PACKAGE_VERSION', meson.project_version())
|
||||||
|
manpage = configure_file(input: 'doc/libevdev.man.in',
|
||||||
|
output: 'libevdev.3',
|
||||||
|
configuration: man_config)
|
||||||
|
install_man(manpage)
|
||||||
|
|
||||||
|
|
||||||
|
# tools
|
||||||
|
if not get_option('tools').disabled()
|
||||||
|
executable('libevdev-events',
|
||||||
|
sources: ['tools/libevdev-events.c'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: dep_libevdev,
|
||||||
|
install: false)
|
||||||
|
executable('libevdev-list-codes',
|
||||||
|
sources: ['tools/libevdev-list-codes.c'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: dep_libevdev,
|
||||||
|
install: false)
|
||||||
|
executable('touchpad-edge-detector',
|
||||||
|
sources: ['tools/touchpad-edge-detector.c'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_libevdev, dep_lm],
|
||||||
|
install: true)
|
||||||
|
executable('mouse-dpi-tool',
|
||||||
|
sources: ['tools/mouse-dpi-tool.c'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: dep_libevdev,
|
||||||
|
install: true)
|
||||||
|
executable('libevdev-tweak-device',
|
||||||
|
sources: ['tools/libevdev-tweak-device.c'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: dep_libevdev,
|
||||||
|
install: true)
|
||||||
|
install_man('tools/libevdev-tweak-device.1',
|
||||||
|
'tools/touchpad-edge-detector.1',
|
||||||
|
'tools/mouse-dpi-tool.1')
|
||||||
|
endif
|
||||||
|
|
||||||
|
# tests
|
||||||
|
dep_check = dependency('check', version: '>= 0.9.9',
|
||||||
|
required: get_option('tests'))
|
||||||
|
if dep_check.found()
|
||||||
|
executable('test-link',
|
||||||
|
sources: ['test/test-link.c'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: dep_libevdev,
|
||||||
|
install: false)
|
||||||
|
executable('test-compile-pedantic',
|
||||||
|
sources: ['test/test-compile-pedantic.c'],
|
||||||
|
c_args: ['-pedantic', '-Werror', '-std=c89'],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: dep_libevdev,
|
||||||
|
install: false)
|
||||||
|
|
||||||
|
src_common = [
|
||||||
|
'test/test-common-uinput.c',
|
||||||
|
'test/test-common-uinput.h',
|
||||||
|
'test/test-common.c',
|
||||||
|
'test/test-common.h',
|
||||||
|
'test/test-main.c',
|
||||||
|
]
|
||||||
|
test_event_codes = executable('test-event-codes',
|
||||||
|
sources: src_common + [
|
||||||
|
'test/test-event-codes.c',
|
||||||
|
'test/test-event-names.c',
|
||||||
|
'test/test-context.c',
|
||||||
|
],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_libevdev, dep_check],
|
||||||
|
install: false)
|
||||||
|
test('test-event-codes', test_event_codes, suite: ['library', 'needs-uinput'])
|
||||||
|
|
||||||
|
test_internals = executable('test-internals',
|
||||||
|
sources: src_common + [
|
||||||
|
'test/test-int-queue.c',
|
||||||
|
],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_libevdev, dep_check],
|
||||||
|
install: false)
|
||||||
|
test('test-internals', test_internals, suite: ['library', 'needs-uinput'])
|
||||||
|
|
||||||
|
test_uinput = executable('test-uinput',
|
||||||
|
sources: src_common + [
|
||||||
|
'test/test-uinput.c',
|
||||||
|
],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_libevdev, dep_check],
|
||||||
|
install: false)
|
||||||
|
test('test-uinput', test_uinput, suite: ['library', 'needs-uinput'])
|
||||||
|
|
||||||
|
test_libevdev = executable('test-libevdev',
|
||||||
|
sources: src_common + [
|
||||||
|
'test/test-libevdev-init.c',
|
||||||
|
'test/test-libevdev-has-event.c',
|
||||||
|
'test/test-libevdev-events.c',
|
||||||
|
],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_libevdev, dep_check],
|
||||||
|
install: false)
|
||||||
|
test('test-libevdev', test_libevdev, suite: ['library', 'needs-uinput'], env: ['CK_DEFAULT_TIMEOUT=10'])
|
||||||
|
|
||||||
|
test_kernel = executable('test-kernel',
|
||||||
|
sources: src_common + [
|
||||||
|
'test/test-kernel.c',
|
||||||
|
],
|
||||||
|
include_directories: [includes_include],
|
||||||
|
dependencies: [dep_libevdev, dep_check],
|
||||||
|
install: false)
|
||||||
|
test('test-kernel', test_kernel, suite: ['kernel', 'needs-uinput'])
|
||||||
|
|
||||||
|
|
||||||
|
valgrind = find_program('valgrind', required: false)
|
||||||
|
if valgrind.found()
|
||||||
|
valgrind_env = environment()
|
||||||
|
valgrind_env.set('CK_TIMEOUT_MULTIPLIER', '10')
|
||||||
|
valgrind_env.set('CK_FORK', 'no')
|
||||||
|
valgrind_env.set('RUNNING_ON_VALGRIND', '1')
|
||||||
|
valgrind_suppressions_file = dir_src_test / 'valgrind.suppressions'
|
||||||
|
add_test_setup('valgrind',
|
||||||
|
exe_wrapper: [ valgrind,
|
||||||
|
'--leak-check=full',
|
||||||
|
'--gen-suppressions=all',
|
||||||
|
'--error-exitcode=3',
|
||||||
|
'--suppressions=' + valgrind_suppressions_file ],
|
||||||
|
env: valgrind_env,
|
||||||
|
timeout_multiplier: 100)
|
||||||
|
else
|
||||||
|
message('valgrind not found, disabling valgrind test suite')
|
||||||
|
endif
|
||||||
|
|
||||||
|
test_static_link = find_program('test/test-static-symbols-leak.sh')
|
||||||
|
test('static-symbols-leak', test_static_link,
|
||||||
|
args: [meson.current_build_dir()],
|
||||||
|
suite: 'static')
|
||||||
|
endif
|
||||||
|
|
||||||
|
doxygen = find_program('doxygen', required: get_option('documentation'))
|
||||||
|
if doxygen.found()
|
||||||
|
src_doxygen = files(
|
||||||
|
# source files
|
||||||
|
dir_src / 'libevdev.h',
|
||||||
|
dir_src / 'libevdev-uinput.h',
|
||||||
|
# style files
|
||||||
|
'doc/style/bootstrap.css',
|
||||||
|
'doc/style/customdoxygen.css',
|
||||||
|
'doc/style/doxy-boot.js',
|
||||||
|
'doc/style/dynsections.js',
|
||||||
|
'doc/style/footer.html',
|
||||||
|
'doc/style/header.html',
|
||||||
|
'doc/style/layout.xml',
|
||||||
|
'doc/style/libevdevdoxygen.css',
|
||||||
|
'doc/style/LICENSE',
|
||||||
|
'doc/style/README.md',
|
||||||
|
'doc/style/style.css',
|
||||||
|
)
|
||||||
|
doxyfiles = []
|
||||||
|
foreach f: src_doxygen
|
||||||
|
df = configure_file(input: f,
|
||||||
|
output: '@PLAINNAME@',
|
||||||
|
copy: true)
|
||||||
|
doxyfiles += [df]
|
||||||
|
endforeach
|
||||||
|
|
||||||
|
doc_config = configuration_data()
|
||||||
|
doc_config.set('PACKAGE_NAME', meson.project_name())
|
||||||
|
doc_config.set('PACKAGE_VERSION', meson.project_version())
|
||||||
|
doc_config.set('builddir', meson.current_build_dir())
|
||||||
|
doc_config.set('top_srcdir', dir_root)
|
||||||
|
doc_config.set('srcdir', dir_root / 'doc')
|
||||||
|
|
||||||
|
doxyfile = configure_file(input: 'doc/libevdev.doxygen.in',
|
||||||
|
output: 'libevdev.doxygen',
|
||||||
|
configuration: doc_config)
|
||||||
|
custom_target('doxygen',
|
||||||
|
input: [doxyfiles, doxyfile] + src_doxygen,
|
||||||
|
output: ['.'],
|
||||||
|
command: [doxygen, doxyfile],
|
||||||
|
install: false,
|
||||||
|
build_by_default: true)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
############ output files ############
|
||||||
|
configure_file(output: 'config.h', configuration: config_h)
|
||||||
16
meson_options.txt
Normal file
16
meson_options.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
option('tests',
|
||||||
|
type: 'feature',
|
||||||
|
value: 'enabled',
|
||||||
|
description: 'Build the tests')
|
||||||
|
option('tools',
|
||||||
|
type: 'feature',
|
||||||
|
value: 'enabled',
|
||||||
|
description: 'Build the tools')
|
||||||
|
option('documentation',
|
||||||
|
type: 'feature',
|
||||||
|
value: 'enabled',
|
||||||
|
description: 'Build the documentation')
|
||||||
|
option('coverity',
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
description: 'Enable coverity build fixes, see meson.build for details')
|
||||||
125
test/Makefile.am
125
test/Makefile.am
|
|
@ -22,10 +22,15 @@ test_static_link_LDADD = $(top_builddir)/libevdev/libevdev.la
|
||||||
test_static_link_LDFLAGS = $(AM_LDFLAGS) -static
|
test_static_link_LDFLAGS = $(AM_LDFLAGS) -static
|
||||||
|
|
||||||
check_local_deps =
|
check_local_deps =
|
||||||
clean_local_deps =
|
|
||||||
|
|
||||||
if ENABLE_RUNTIME_TESTS
|
if ENABLE_RUNTIME_TESTS
|
||||||
run_tests = test-libevdev test-kernel
|
run_tests = \
|
||||||
|
test-libevdev \
|
||||||
|
test-kernel \
|
||||||
|
test-uinput \
|
||||||
|
test-event-codes \
|
||||||
|
test-libevdev-internals \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
.NOTPARALLEL:
|
.NOTPARALLEL:
|
||||||
|
|
||||||
|
|
@ -33,15 +38,7 @@ noinst_PROGRAMS += $(run_tests)
|
||||||
|
|
||||||
TESTS = $(run_tests)
|
TESTS = $(run_tests)
|
||||||
|
|
||||||
libevdev_sources = $(top_srcdir)/libevdev/libevdev.c \
|
common_sources = \
|
||||||
$(top_srcdir)/libevdev/libevdev.h \
|
|
||||||
$(top_srcdir)/libevdev/libevdev-names.c \
|
|
||||||
$(top_srcdir)/libevdev/libevdev-uinput.h \
|
|
||||||
$(top_srcdir)/libevdev/libevdev-uinput.c \
|
|
||||||
$(top_srcdir)/libevdev/libevdev-uinput-int.h \
|
|
||||||
$(top_srcdir)/libevdev/libevdev-util.h \
|
|
||||||
$(top_srcdir)/libevdev/libevdev-int.h
|
|
||||||
common_sources = $(libevdev_sources) \
|
|
||||||
test-common-uinput.c \
|
test-common-uinput.c \
|
||||||
test-common-uinput.h \
|
test-common-uinput.h \
|
||||||
test-common.c \
|
test-common.c \
|
||||||
|
|
@ -51,67 +48,58 @@ common_sources = $(libevdev_sources) \
|
||||||
AM_CPPFLAGS += $(CHECK_CFLAGS) $(GCOV_CFLAGS)
|
AM_CPPFLAGS += $(CHECK_CFLAGS) $(GCOV_CFLAGS)
|
||||||
AM_LDFLAGS += $(GCOV_LDFLAGS)
|
AM_LDFLAGS += $(GCOV_LDFLAGS)
|
||||||
|
|
||||||
test_libevdev_SOURCES = \
|
test_event_codes_SOURCES = \
|
||||||
test-main.c \
|
test-main.c \
|
||||||
test-event-names.c \
|
|
||||||
test-event-codes.c \
|
test-event-codes.c \
|
||||||
test-libevdev-init.c \
|
test-event-names.c \
|
||||||
test-libevdev-has-event.c \
|
test-context.c \
|
||||||
|
$(common_sources)
|
||||||
|
test_event_codes_LDADD = $(CHECK_LIBS) $(top_builddir)/libevdev/libevdev.la
|
||||||
|
test_event_codes_LDFLAGS = -no-install
|
||||||
|
|
||||||
|
test_libevdev_internals_SOURCES = \
|
||||||
|
test-main.c \
|
||||||
test-int-queue.c \
|
test-int-queue.c \
|
||||||
test-libevdev-events.c \
|
$(common_sources)
|
||||||
|
test_libevdev_internals_LDADD = $(CHECK_LIBS) $(top_builddir)/libevdev/libevdev.la
|
||||||
|
test_libevdev_internals_LDFLAGS = -no-install
|
||||||
|
|
||||||
|
test_uinput_SOURCES = \
|
||||||
|
test-main.c \
|
||||||
test-uinput.c \
|
test-uinput.c \
|
||||||
$(common_sources)
|
$(common_sources)
|
||||||
|
test_uinput_LDADD = $(CHECK_LIBS) $(top_builddir)/libevdev/libevdev.la
|
||||||
|
test_uinput_LDFLAGS = -no-install
|
||||||
|
|
||||||
test_libevdev_LDADD = $(CHECK_LIBS)
|
test_libevdev_SOURCES = \
|
||||||
|
test-main.c \
|
||||||
|
test-libevdev-init.c \
|
||||||
|
test-libevdev-has-event.c \
|
||||||
|
test-libevdev-events.c \
|
||||||
|
$(common_sources)
|
||||||
|
|
||||||
|
test_libevdev_LDADD = $(CHECK_LIBS) $(top_builddir)/libevdev/libevdev.la
|
||||||
|
test_libevdev_LDFLAGS = -no-install
|
||||||
|
|
||||||
test_kernel_SOURCES = \
|
test_kernel_SOURCES = \
|
||||||
|
test-main.c \
|
||||||
test-kernel.c \
|
test-kernel.c \
|
||||||
$(common_sources)
|
$(common_sources)
|
||||||
|
|
||||||
test_kernel_CFLAGS = -I$(top_srcdir)
|
test_kernel_CFLAGS = -I$(top_srcdir)
|
||||||
test_kernel_LDADD = $(CHECK_LIBS)
|
test_kernel_LDADD = $(CHECK_LIBS) $(top_builddir)/libevdev/libevdev.la
|
||||||
|
|
||||||
if HAVE_VALGRIND
|
|
||||||
VALGRIND_FLAGS=--leak-check=full \
|
|
||||||
--quiet \
|
|
||||||
--error-exitcode=3 \
|
|
||||||
--suppressions=$(srcdir)/valgrind.suppressions
|
|
||||||
|
|
||||||
valgrind:
|
|
||||||
$(MAKE) check-TESTS LOG_COMPILER="$(VALGRIND)" LOG_FLAGS="$(VALGRIND_FLAGS)"
|
|
||||||
|
|
||||||
check_local_deps += valgrind
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
EXTRA_DIST = valgrind.suppressions
|
|
||||||
|
|
||||||
if GCOV_ENABLED
|
if GCOV_ENABLED
|
||||||
|
|
||||||
CLEANFILES = gcov-report.txt
|
CLEANFILES = gcov-reports/*.gcov gcov-reports/summary.txt *.gcno *.gcda
|
||||||
|
|
||||||
gcov-clean:
|
gcov-report: generate-gcov-report.sh
|
||||||
@rm -f *.gcov
|
$(AM_V_GEN)$(srcdir)/generate-gcov-report.sh gcov-reports $(top_builddir)/libevdev $(builddir)
|
||||||
|
|
||||||
gcov-report.txt: gcov-clean check-TESTS
|
gcov: gcov-report
|
||||||
$(AM_V_GEN)(rm -rf $@; \
|
@cat gcov-reports/summary.txt
|
||||||
echo "========== coverage report ========" >> $@; \
|
|
||||||
for file in `find $(top_srcdir)/libevdev -name "*.c" -printf "%P\n"`; do \
|
|
||||||
gcov $$file > /dev/null; \
|
|
||||||
if test -f $$file.gcov; then \
|
|
||||||
total=`grep -v " -:" $$file.gcov | wc -l`; \
|
|
||||||
missing=`grep "#####" $$file.gcov | wc -l`; \
|
|
||||||
hit=$$((total - missing)); \
|
|
||||||
echo -e "$$file: total lines: $$total not tested: $$missing ($$((($$hit * 100)/$$total))%)"; \
|
|
||||||
fi \
|
|
||||||
done >> $@; \
|
|
||||||
echo "========== =============== ========" >> $@; \
|
|
||||||
)
|
|
||||||
|
|
||||||
gcov: gcov-report.txt
|
|
||||||
@cat gcov-report.txt
|
|
||||||
|
|
||||||
check_local_deps += gcov
|
check_local_deps += gcov
|
||||||
clean_local_deps += gcov-clean
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
|
@ -121,37 +109,22 @@ gcov-report.txt:
|
||||||
gcov:
|
gcov:
|
||||||
@true
|
@true
|
||||||
|
|
||||||
gcov-clean:
|
|
||||||
@true
|
|
||||||
|
|
||||||
endif # HAVE_VALGRIND
|
endif # GCOV_ENABLED
|
||||||
|
|
||||||
.PHONY: gcov gcov-clean gcov-report.txt
|
.PHONY: gcov gcov-clean gcov-report
|
||||||
|
|
||||||
endif # ENABLE_RUNTIME_TESTS
|
endif # ENABLE_RUNTIME_TESTS
|
||||||
|
|
||||||
if ENABLE_STATIC_SYMBOL_LEAKS_TEST
|
if ENABLE_STATIC_SYMBOL_LEAKS_TEST
|
||||||
# Hack to check for leaking symbols in the static library.
|
static-symbol-leaks: test-static-link test-static-symbols-leak.sh
|
||||||
# See https://bugs.freedesktop.org/show_bug.cgi?id=82785
|
$(AM_V_GEN) $(srcdir)/test-static-symbols-leak.sh $(builddir)
|
||||||
# Note the spaces in the expressions! After the first grep, each line
|
|
||||||
# is " T symbol_name"
|
|
||||||
static-symbol-leaks: test-static-link
|
|
||||||
$(AM_V_GEN)(\
|
|
||||||
$(NM) --extern-only $(builddir)/test-static-link | \
|
|
||||||
grep -o -e " T .*" | \
|
|
||||||
grep -v -e " main$$" \
|
|
||||||
-e " atexit" \
|
|
||||||
-e " *gcov.*" \
|
|
||||||
-e " _.*" \
|
|
||||||
-e " libevdev_*" && \
|
|
||||||
echo "Leaking symbols found" && \
|
|
||||||
exit 1 || exit 0 \
|
|
||||||
)
|
|
||||||
|
|
||||||
check_local_deps += static-symbol-leaks
|
check_local_deps += static-symbol-leaks
|
||||||
|
|
||||||
endif # HAVE_NM
|
endif # HAVE_NM
|
||||||
|
|
||||||
|
EXTRA_DIST = valgrind.suppressions generate-gcov-report.sh test-static-symbols-leak.sh
|
||||||
|
|
||||||
check-local: $(check_local_deps)
|
check-local: $(check_local_deps)
|
||||||
|
|
||||||
clean-local: $(clean_local_deps)
|
|
||||||
rm -f *.gcno *.gcda
|
|
||||||
|
|
|
||||||
40
test/generate-gcov-report.sh
Executable file
40
test/generate-gcov-report.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
echo "Usage: ./generate-gcov-report.sh <rel-target-dir> <srcdir> [<srcdir> ... ]"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
target_dir=$1
|
||||||
|
shift
|
||||||
|
source_dirs=$*
|
||||||
|
|
||||||
|
if [[ "${target_dir:0:1}" != '/' ]]; then
|
||||||
|
target_dir="$PWD/$target_dir"
|
||||||
|
fi
|
||||||
|
summary_file="$target_dir/summary.txt"
|
||||||
|
|
||||||
|
mkdir -p "$target_dir"
|
||||||
|
rm -f "$target_dir"/*.gcov
|
||||||
|
|
||||||
|
for dir in $source_dirs; do
|
||||||
|
pushd "$dir" > /dev/null
|
||||||
|
for file in *.c; do
|
||||||
|
find ./ -name "*${file/\.c/.gcda}" -exec gcov {} \; > /dev/null
|
||||||
|
done
|
||||||
|
find ./ -name "*.gcov" \! -path "*/`basename "$target_dir"`/*" -exec mv {} "$target_dir" \;
|
||||||
|
popd > /dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "========== coverage report ========" > "$summary_file"
|
||||||
|
for file in "$target_dir"/*.gcov; do
|
||||||
|
total=`grep -v " -:" "$file" | wc -l`
|
||||||
|
missing=`grep "#####" "$file" | wc -l`
|
||||||
|
hit=$((total - missing));
|
||||||
|
percent=$((($hit * 100)/$total))
|
||||||
|
fname=`basename "$file"`
|
||||||
|
printf "%-32s total lines: %4s not tested: %4s (%3s%%)\n" "$fname" "$total" "$missing" "$percent">> "$summary_file"
|
||||||
|
done
|
||||||
|
echo "========== =============== ========" >> "$summary_file"
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <libevdev/libevdev.h>
|
#include <libevdev/libevdev.h>
|
||||||
|
|
||||||
#define DEFAULT_IDS NULL
|
#define DEFAULT_IDS NULL
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
@ -89,6 +72,7 @@ void test_create_abs_device(struct uinput_device **uidev_return,
|
||||||
|
|
||||||
va_start(args, abs);
|
va_start(args, abs);
|
||||||
rc = uinput_device_set_event_bits_v(uidev, args);
|
rc = uinput_device_set_event_bits_v(uidev, args);
|
||||||
|
ck_assert_msg(rc == 0, "Failed to set uinput bits");
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
while (--nabs >= 0) {
|
while (--nabs >= 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,57 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <libevdev/libevdev.h>
|
#include <libevdev/libevdev.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
|
|
||||||
#ifndef _TEST_COMMON_H_
|
#ifndef _TEST_COMMON_H_
|
||||||
#define _TEST_COMMON_H_
|
#define _TEST_COMMON_H_
|
||||||
|
|
||||||
|
struct libevdev_test {
|
||||||
|
const char *name;
|
||||||
|
Suite* (*setup)(void);
|
||||||
|
bool needs_root_privileges;
|
||||||
|
} __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
#define _TEST_SUITE(name, root_privs) \
|
||||||
|
static Suite* (name##_setup)(void); \
|
||||||
|
static const struct libevdev_test _test \
|
||||||
|
__attribute__((used)) \
|
||||||
|
__attribute__((section ("test_section"))) = { \
|
||||||
|
#name, name##_setup, root_privs \
|
||||||
|
}; \
|
||||||
|
static Suite* (name##_setup)(void)
|
||||||
|
|
||||||
|
#define TEST_SUITE(name) \
|
||||||
|
_TEST_SUITE(name, false)
|
||||||
|
|
||||||
|
#define TEST_SUITE_ROOT_PRIVILEGES(name) \
|
||||||
|
_TEST_SUITE(name, true)
|
||||||
|
|
||||||
#define TEST_DEVICE_NAME "libevdev test device"
|
#define TEST_DEVICE_NAME "libevdev test device"
|
||||||
|
|
||||||
|
#define add_test(suite, func) do { \
|
||||||
|
TCase *tc = tcase_create(#func); \
|
||||||
|
tcase_add_test(tc, func); \
|
||||||
|
suite_add_tcase(suite, tc); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#include "test-common-uinput.h"
|
#include "test-common-uinput.h"
|
||||||
|
|
||||||
|
#define assert_event(e_, t, c, v) \
|
||||||
|
do { \
|
||||||
|
const struct input_event *e = (e_); \
|
||||||
|
ck_assert_int_eq(e->type, (t)); \
|
||||||
|
ck_assert_int_eq(e->code, (c)); \
|
||||||
|
ck_assert_int_eq(e->value, (v)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
void test_create_device(struct uinput_device **uidev,
|
void test_create_device(struct uinput_device **uidev,
|
||||||
struct libevdev **dev,
|
struct libevdev **dev,
|
||||||
...);
|
...);
|
||||||
|
|
@ -51,4 +71,23 @@ void test_logfunc_ignore_error(enum libevdev_log_priority priority,
|
||||||
const char *file, int line,
|
const char *file, int line,
|
||||||
const char *func,
|
const char *func,
|
||||||
const char *format, va_list args);
|
const char *format, va_list args);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
print_event(const struct input_event *ev)
|
||||||
|
{
|
||||||
|
if (ev->type == EV_SYN)
|
||||||
|
printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
|
||||||
|
ev->input_event_sec,
|
||||||
|
ev->input_event_usec,
|
||||||
|
libevdev_event_type_get_name(ev->type));
|
||||||
|
else
|
||||||
|
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
|
||||||
|
ev->input_event_sec,
|
||||||
|
ev->input_event_usec,
|
||||||
|
ev->type,
|
||||||
|
libevdev_event_type_get_name(ev->type),
|
||||||
|
ev->code,
|
||||||
|
libevdev_event_code_get_name(ev->type, ev->code),
|
||||||
|
ev->value);
|
||||||
|
}
|
||||||
#endif /* _TEST_COMMON_H_ */
|
#endif /* _TEST_COMMON_H_ */
|
||||||
|
|
|
||||||
161
test/test-context.c
Normal file
161
test/test-context.c
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* Copyright © 2019 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "test-common.h"
|
||||||
|
|
||||||
|
START_TEST(test_info)
|
||||||
|
{
|
||||||
|
struct libevdev *d = libevdev_new();
|
||||||
|
|
||||||
|
libevdev_set_name(d, "some name");
|
||||||
|
ck_assert_str_eq(libevdev_get_name(d), "some name");
|
||||||
|
libevdev_set_phys(d, "physical");
|
||||||
|
ck_assert_str_eq(libevdev_get_phys(d), "physical");
|
||||||
|
libevdev_set_uniq(d, "very unique");
|
||||||
|
ck_assert_str_eq(libevdev_get_uniq(d), "very unique");
|
||||||
|
|
||||||
|
libevdev_set_id_bustype(d, 1);
|
||||||
|
libevdev_set_id_vendor(d, 2);
|
||||||
|
libevdev_set_id_product(d, 3);
|
||||||
|
libevdev_set_id_version(d, 4);
|
||||||
|
ck_assert_int_eq(libevdev_get_id_bustype(d), 1);
|
||||||
|
ck_assert_int_eq(libevdev_get_id_vendor(d), 2);
|
||||||
|
ck_assert_int_eq(libevdev_get_id_product(d), 3);
|
||||||
|
ck_assert_int_eq(libevdev_get_id_version(d), 4);
|
||||||
|
|
||||||
|
libevdev_free(d);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_properties)
|
||||||
|
{
|
||||||
|
for (unsigned prop = 0; prop < INPUT_PROP_CNT; prop++) {
|
||||||
|
struct libevdev *d = libevdev_new();
|
||||||
|
|
||||||
|
ck_assert(!libevdev_has_property(d, prop));
|
||||||
|
libevdev_enable_property(d, prop);
|
||||||
|
ck_assert(libevdev_has_property(d, prop));
|
||||||
|
libevdev_free(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_bits)
|
||||||
|
{
|
||||||
|
for (unsigned type = 1; type < EV_CNT; type++) {
|
||||||
|
unsigned max = libevdev_event_type_get_max(type);
|
||||||
|
|
||||||
|
if((int)max == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (unsigned code = 0; code <= max; code++) {
|
||||||
|
struct libevdev *d = libevdev_new();
|
||||||
|
const struct input_absinfo abs = {
|
||||||
|
.minimum = 10,
|
||||||
|
.maximum = 20,
|
||||||
|
.fuzz = 30,
|
||||||
|
.flat = 40,
|
||||||
|
.resolution = 50,
|
||||||
|
};
|
||||||
|
const void *data = NULL;
|
||||||
|
|
||||||
|
if (type == EV_ABS || type == EV_REP)
|
||||||
|
data = &abs;
|
||||||
|
|
||||||
|
ck_assert(!libevdev_has_event_code(d, type, code));
|
||||||
|
libevdev_enable_event_code(d, type, code, data);
|
||||||
|
ck_assert(libevdev_has_event_code(d, type, code));
|
||||||
|
libevdev_free(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_mt_slots_enable_disable)
|
||||||
|
{
|
||||||
|
struct libevdev *d = libevdev_new();
|
||||||
|
struct input_absinfo abs = {0};
|
||||||
|
|
||||||
|
abs.maximum = 5;
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
ck_assert(libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), 6);
|
||||||
|
|
||||||
|
libevdev_disable_event_code(d, EV_ABS, ABS_MT_SLOT);
|
||||||
|
ck_assert(!libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), -1);
|
||||||
|
|
||||||
|
abs.maximum = 2;
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
ck_assert(libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), 3);
|
||||||
|
|
||||||
|
libevdev_free(d);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_mt_slots_increase_decrease)
|
||||||
|
{
|
||||||
|
struct libevdev *d = libevdev_new();
|
||||||
|
struct input_absinfo abs = {0};
|
||||||
|
|
||||||
|
abs.maximum = 5;
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
ck_assert(libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), 6);
|
||||||
|
|
||||||
|
abs.maximum = 2;
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
ck_assert(libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), 3);
|
||||||
|
|
||||||
|
abs.maximum = 6;
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
ck_assert(libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), 7);
|
||||||
|
|
||||||
|
abs.maximum = 10;
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
ck_assert(libevdev_has_event_code(d, EV_ABS, ABS_MT_SLOT));
|
||||||
|
ck_assert_int_eq(libevdev_get_num_slots(d), 11);
|
||||||
|
|
||||||
|
libevdev_free(d);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_mt_tracking_id)
|
||||||
|
{
|
||||||
|
struct libevdev *d = libevdev_new();
|
||||||
|
struct input_absinfo abs = { .maximum = 5 };
|
||||||
|
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_SLOT, &abs);
|
||||||
|
|
||||||
|
/* Not yet enabled, so 0. This is technically undefined */
|
||||||
|
for (int slot = 0; slot < 5; slot++)
|
||||||
|
ck_assert_int_eq(libevdev_get_slot_value(d, 0, ABS_MT_TRACKING_ID), 0);
|
||||||
|
|
||||||
|
libevdev_enable_event_code(d, EV_ABS, ABS_MT_TRACKING_ID, &abs);
|
||||||
|
|
||||||
|
for (int slot = 0; slot < 5; slot++)
|
||||||
|
ck_assert_int_eq(libevdev_get_slot_value(d, 0, ABS_MT_TRACKING_ID), -1);
|
||||||
|
|
||||||
|
libevdev_free(d);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
TEST_SUITE(event_name_suite)
|
||||||
|
{
|
||||||
|
Suite *s = suite_create("Context manipulation");
|
||||||
|
|
||||||
|
add_test(s, test_info);
|
||||||
|
add_test(s, test_properties);
|
||||||
|
add_test(s, test_bits);
|
||||||
|
add_test(s, test_mt_slots_enable_disable);
|
||||||
|
add_test(s, test_mt_slots_increase_decrease);
|
||||||
|
add_test(s, test_mt_tracking_id);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
@ -1,29 +1,12 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
* Copyright © 2013 David Herrmann <dh.herrmann@gmail.com>
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
||||||
START_TEST(test_type_codes)
|
START_TEST(test_type_names)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(libevdev_event_type_from_name("EV_SYN"), EV_SYN);
|
ck_assert_int_eq(libevdev_event_type_from_name("EV_SYN"), EV_SYN);
|
||||||
ck_assert_int_eq(libevdev_event_type_from_name("EV_KEY"), EV_KEY);
|
ck_assert_int_eq(libevdev_event_type_from_name("EV_KEY"), EV_KEY);
|
||||||
|
|
@ -43,7 +26,7 @@ START_TEST(test_type_codes)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_type_invalid)
|
START_TEST(test_type_names_invalid)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(libevdev_event_type_from_name("EV_Syn"), -1);
|
ck_assert_int_eq(libevdev_event_type_from_name("EV_Syn"), -1);
|
||||||
ck_assert_int_eq(libevdev_event_type_from_name("ev_SYN"), -1);
|
ck_assert_int_eq(libevdev_event_type_from_name("ev_SYN"), -1);
|
||||||
|
|
@ -55,7 +38,42 @@ START_TEST(test_type_invalid)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_key_codes)
|
START_TEST(test_type_name_lookup)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("SYN_REPORT"), EV_SYN);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("KEY_A"), EV_KEY);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("REL_Z"), EV_REL);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("ABS_Z"), EV_ABS);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("MSC_SERIAL"), EV_MSC);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("SND_TONE"), EV_SND);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("SW_TABLET_MODE"), EV_SW);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("LED_CHARGING"), EV_LED);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("REP_PERIOD"), EV_REP);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("FF_SPRING"), EV_FF);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("FF_STATUS_STOPPED"), EV_FF_STATUS);
|
||||||
|
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name_n("KEY_1zzzzz", 5), EV_KEY);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name_n("ABS_Zooom", 5), EV_ABS);
|
||||||
|
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("KEY_MAX"), EV_KEY);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("REL_MAX"), EV_REL);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_code_name("ABS_MAX"), EV_ABS);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_type_name_lookup_invalid)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_name("SYN_REPORTED"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_name("syn_blah"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_name("SYN_"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_name("KEY_BANANA"), -1);
|
||||||
|
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_name_n("KEY_BA", 6), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_type_from_name_n("KEY_BLAH", 8), -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_code_names)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_REPORT"), SYN_REPORT);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_REPORT"), SYN_REPORT);
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_ABS, "ABS_X"), ABS_X);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_ABS, "ABS_X"), ABS_X);
|
||||||
|
|
@ -72,13 +90,37 @@ START_TEST(test_key_codes)
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "KEY_0"), KEY_0);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "KEY_0"), KEY_0);
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_GAIN"), FF_GAIN);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_GAIN"), FF_GAIN);
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS_MAX"), FF_STATUS_MAX);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_FF_STATUS, "FF_STATUS_MAX"), FF_STATUS_MAX);
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_SW, "SW_MAX"), SW_MAX);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_SW, "SW_PEN_INSERTED"), SW_PEN_INSERTED);
|
||||||
|
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name_n(EV_ABS, "ABS_YXZ", 5), ABS_Y);
|
ck_assert_int_eq(libevdev_event_code_from_name_n(EV_ABS, "ABS_YXZ", 5), ABS_Y);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_key_invalid)
|
START_TEST(test_code_name_lookup)
|
||||||
|
{
|
||||||
|
/* Same as test_code_names() but without the type */
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SYN_REPORT"), SYN_REPORT);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("ABS_X"), ABS_X);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("BTN_A"), BTN_A);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_A"), KEY_A);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("REL_X"), REL_X);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("MSC_RAW"), MSC_RAW);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("LED_KANA"), LED_KANA);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SND_BELL"), SND_BELL);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("REP_DELAY"), REP_DELAY);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SYN_DROPPED"), SYN_DROPPED);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_RESERVED"), KEY_RESERVED);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("BTN_0"), BTN_0);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_0"), KEY_0);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_GAIN"), FF_GAIN);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS_MAX"), FF_STATUS_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SW_PEN_INSERTED"), SW_PEN_INSERTED);
|
||||||
|
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name_n("ABS_YXZ", 5), ABS_Y);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_code_names_invalid)
|
||||||
{
|
{
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_MAX, "MAX_FAKE"), -1);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_MAX, "MAX_FAKE"), -1);
|
||||||
ck_assert_int_eq(libevdev_event_code_from_name(EV_CNT, "CNT_FAKE"), -1);
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_CNT, "CNT_FAKE"), -1);
|
||||||
|
|
@ -99,6 +141,76 @@ START_TEST(test_key_invalid)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_code_name_lookup_invalid)
|
||||||
|
{
|
||||||
|
/* Same as test_code_names_invalid() but without the type */
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("MAX_FAKE"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("CNT_FAKE"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("PWR_SOMETHING"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("EV_ABS"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("ABS_XY"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("BTN_GAMEPAD"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("BUS_PCI"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS_"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_STATUS_"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("ID_BUS"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SND_CNT"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SW_CNT"), -1);
|
||||||
|
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name_n("ABS_X", 4), -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_code_names_max)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_SYN, "SYN_MAX"), SYN_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_KEY, "KEY_MAX"), KEY_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_REL, "REL_MAX"), REL_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_ABS, "ABS_MAX"), ABS_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_MSC, "MSC_MAX"), MSC_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_SW, "SW_MAX"), SW_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_LED, "LED_MAX"), LED_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_SND, "SND_MAX"), SND_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_REP, "REP_MAX"), REP_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_name(EV_FF, "FF_MAX"), FF_MAX);
|
||||||
|
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SYN_MAX"), SYN_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("KEY_MAX"), KEY_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("REL_MAX"), REL_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("ABS_MAX"), ABS_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("MSC_MAX"), MSC_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SW_MAX"), SW_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("LED_MAX"), LED_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("SND_MAX"), SND_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("REP_MAX"), REP_MAX);
|
||||||
|
ck_assert_int_eq(libevdev_event_code_from_code_name("FF_MAX"), FF_MAX);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_value_names)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "MT_TOOL_PALM"), MT_TOOL_PALM);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "MT_TOOL_FINGER"), MT_TOOL_FINGER);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "MT_TOOL_PEN"), MT_TOOL_PEN);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "MT_TOOL_MAX"), MT_TOOL_MAX);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_value_names_invalid)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_SYN, REL_X, "MT_TOOL_PALM"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_REL, REL_X, "MT_TOOL_PALM"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_X, "MT_TOOL_PALM"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "MT_TOOL_"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "MT_TOOL_PALMA"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, ""), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "EV_ABS"), -1);
|
||||||
|
ck_assert_int_eq(libevdev_event_value_from_name(EV_ABS, ABS_MT_TOOL_TYPE, "ABS_X"), -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_properties)
|
START_TEST(test_properties)
|
||||||
{
|
{
|
||||||
struct prop {
|
struct prop {
|
||||||
|
|
@ -131,25 +243,26 @@ START_TEST(test_properties_invalid)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
Suite *
|
TEST_SUITE(event_code_suite)
|
||||||
event_code_suite(void)
|
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("Event codes");
|
Suite *s = suite_create("Event codes");
|
||||||
|
|
||||||
TCase *tc = tcase_create("type tests");
|
add_test(s, test_type_names);
|
||||||
tcase_add_test(tc, test_type_codes);
|
add_test(s, test_type_names_invalid);
|
||||||
tcase_add_test(tc, test_type_invalid);
|
add_test(s, test_type_name_lookup);
|
||||||
suite_add_tcase(s, tc);
|
add_test(s, test_type_name_lookup_invalid);
|
||||||
|
|
||||||
tc = tcase_create("key tests");
|
add_test(s, test_code_names);
|
||||||
tcase_add_test(tc, test_key_codes);
|
add_test(s, test_code_name_lookup);
|
||||||
tcase_add_test(tc, test_key_invalid);
|
add_test(s, test_code_names_invalid);
|
||||||
suite_add_tcase(s, tc);
|
add_test(s, test_code_name_lookup_invalid);
|
||||||
|
add_test(s, test_code_names_max);
|
||||||
|
|
||||||
tc = tcase_create("property tests");
|
add_test(s, test_value_names);
|
||||||
tcase_add_test(tc, test_properties);
|
add_test(s, test_value_names_invalid);
|
||||||
tcase_add_test(tc, test_properties_invalid);
|
|
||||||
suite_add_tcase(s, tc);
|
add_test(s, test_properties);
|
||||||
|
add_test(s, test_properties_invalid);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
||||||
START_TEST(test_limits)
|
START_TEST(test_limits)
|
||||||
|
|
@ -36,6 +19,7 @@ START_TEST(test_limits)
|
||||||
ck_assert(libevdev_event_code_get_name(EV_REP, REP_MAX + 1) == NULL);
|
ck_assert(libevdev_event_code_get_name(EV_REP, REP_MAX + 1) == NULL);
|
||||||
ck_assert(libevdev_event_code_get_name(EV_FF, FF_MAX + 1) == NULL);
|
ck_assert(libevdev_event_code_get_name(EV_FF, FF_MAX + 1) == NULL);
|
||||||
ck_assert(libevdev_event_code_get_name(EV_MAX + 1, 0) == NULL);
|
ck_assert(libevdev_event_code_get_name(EV_MAX + 1, 0) == NULL);
|
||||||
|
ck_assert(libevdev_event_value_get_name(EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_MAX + 1) == NULL);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
@ -143,6 +127,15 @@ START_TEST(test_code_snd_name)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_code_rep_name)
|
||||||
|
{
|
||||||
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_REP, REP_DELAY), "REP_DELAY");
|
||||||
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_REP, REP_PERIOD), "REP_PERIOD");
|
||||||
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_REP, REP_MAX), "REP_PERIOD");
|
||||||
|
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_code_msc_name)
|
START_TEST(test_code_msc_name)
|
||||||
{
|
{
|
||||||
/* pick out a few only */
|
/* pick out a few only */
|
||||||
|
|
@ -164,7 +157,8 @@ START_TEST(test_code_sw_name)
|
||||||
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_LID), "SW_LID");
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_LID), "SW_LID");
|
||||||
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_RFKILL_ALL), "SW_RFKILL_ALL");
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_RFKILL_ALL), "SW_RFKILL_ALL");
|
||||||
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_LINEIN_INSERT), "SW_LINEIN_INSERT");
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_LINEIN_INSERT), "SW_LINEIN_INSERT");
|
||||||
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_MAX), "SW_MAX");
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_PEN_INSERTED), "SW_PEN_INSERTED");
|
||||||
|
ck_assert_str_eq(libevdev_event_code_get_name(EV_SW, SW_MAX), "SW_USB_INSERT");
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
|
@ -191,6 +185,35 @@ START_TEST(test_code_syn_name)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_value_name)
|
||||||
|
{
|
||||||
|
unsigned int type, code;
|
||||||
|
int value;
|
||||||
|
|
||||||
|
for (type = 0; type < EV_MAX; type++) {
|
||||||
|
int max = libevdev_event_type_get_max(type);
|
||||||
|
|
||||||
|
if (max == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (code = 0; code < (unsigned int)max; code++) {
|
||||||
|
if (type == EV_ABS && code == ABS_MT_TOOL_TYPE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (value = 0; value < 0xff; value++) {
|
||||||
|
ck_assert(libevdev_event_value_get_name(type, code, value) == NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ck_assert_str_eq(libevdev_event_value_get_name(EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER), "MT_TOOL_FINGER");
|
||||||
|
ck_assert_str_eq(libevdev_event_value_get_name(EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM), "MT_TOOL_PALM");
|
||||||
|
ck_assert_str_eq(libevdev_event_value_get_name(EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PEN), "MT_TOOL_PEN");
|
||||||
|
ck_assert_str_eq(libevdev_event_value_get_name(EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_MAX), "MT_TOOL_MAX");
|
||||||
|
ck_assert(libevdev_event_value_get_name(EV_ABS, ABS_MT_TOOL_TYPE, -1) == NULL);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_prop_name)
|
START_TEST(test_prop_name)
|
||||||
{
|
{
|
||||||
ck_assert_str_eq(libevdev_property_get_name(INPUT_PROP_POINTER), "INPUT_PROP_POINTER");
|
ck_assert_str_eq(libevdev_property_get_name(INPUT_PROP_POINTER), "INPUT_PROP_POINTER");
|
||||||
|
|
@ -261,40 +284,31 @@ START_TEST(test_event_code)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
Suite *
|
TEST_SUITE(event_name_suite)
|
||||||
event_name_suite(void)
|
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("Event names");
|
Suite *s = suite_create("Event names");
|
||||||
|
|
||||||
TCase *tc = tcase_create("type limits");
|
add_test(s, test_limits);
|
||||||
tcase_add_test(tc, test_limits);
|
add_test(s, test_event_type_max);
|
||||||
tcase_add_test(tc, test_event_type_max);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("type names");
|
add_test(s, test_type_name);
|
||||||
tcase_add_test(tc, test_type_name);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("code names");
|
add_test(s, test_code_abs_name);
|
||||||
tcase_add_test(tc, test_code_abs_name);
|
add_test(s, test_code_rel_name);
|
||||||
tcase_add_test(tc, test_code_rel_name);
|
add_test(s, test_code_key_name);
|
||||||
tcase_add_test(tc, test_code_key_name);
|
add_test(s, test_code_led_name);
|
||||||
tcase_add_test(tc, test_code_led_name);
|
add_test(s, test_code_snd_name);
|
||||||
tcase_add_test(tc, test_code_snd_name);
|
add_test(s, test_code_rep_name);
|
||||||
tcase_add_test(tc, test_code_msc_name);
|
add_test(s, test_code_msc_name);
|
||||||
tcase_add_test(tc, test_code_sw_name);
|
add_test(s, test_code_sw_name);
|
||||||
tcase_add_test(tc, test_code_ff_name);
|
add_test(s, test_code_ff_name);
|
||||||
tcase_add_test(tc, test_code_syn_name);
|
add_test(s, test_code_syn_name);
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("prop names");
|
add_test(s, test_value_name);
|
||||||
tcase_add_test(tc, test_prop_name);
|
add_test(s, test_prop_name);
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("event values");
|
add_test(s, test_event_type);
|
||||||
tcase_add_test(tc, test_event_type);
|
add_test(s, test_event_code);
|
||||||
tcase_add_test(tc, test_event_code);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <libevdev/libevdev-int.h>
|
#include <libevdev/libevdev-int.h>
|
||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
@ -33,9 +16,6 @@ START_TEST(test_queue_alloc)
|
||||||
rc = queue_alloc(&dev, 0);
|
rc = queue_alloc(&dev, 0);
|
||||||
ck_assert_int_eq(rc, -ENOMEM);
|
ck_assert_int_eq(rc, -ENOMEM);
|
||||||
|
|
||||||
rc = queue_alloc(&dev, ULONG_MAX);
|
|
||||||
ck_assert_int_eq(rc, -ENOMEM);
|
|
||||||
|
|
||||||
rc = queue_alloc(&dev, 100);
|
rc = queue_alloc(&dev, 100);
|
||||||
ck_assert_int_eq(rc, 0);
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
|
@ -329,8 +309,7 @@ START_TEST(test_queue_set_num_elements)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
Suite *
|
TEST_SUITE(queue_suite)
|
||||||
queue_suite(void)
|
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("Event queue");
|
Suite *s = suite_create("Event queue");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2014 Red Hat, Inc.
|
* Copyright © 2014 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -61,15 +44,17 @@ START_TEST(test_revoke)
|
||||||
uinput_device_event(uidev, EV_REL, REL_X, 1);
|
uinput_device_event(uidev, EV_REL, REL_X, 1);
|
||||||
uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
|
uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1);
|
for (int i = 0; i < 2; i++) {
|
||||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1);
|
||||||
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
|
||||||
rc = libevdev_next_event(dev2, LIBEVDEV_READ_FLAG_NORMAL, &ev2);
|
rc = libevdev_next_event(dev2, LIBEVDEV_READ_FLAG_NORMAL, &ev2);
|
||||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
|
||||||
ck_assert_int_eq(ev1.type, ev2.type);
|
ck_assert_int_eq(ev1.type, ev2.type);
|
||||||
ck_assert_int_eq(ev1.code, ev2.code);
|
ck_assert_int_eq(ev1.code, ev2.code);
|
||||||
ck_assert_int_eq(ev1.value, ev2.value);
|
ck_assert_int_eq(ev1.value, ev2.value);
|
||||||
|
}
|
||||||
|
|
||||||
/* revoke first device, expect it closed, second device still open */
|
/* revoke first device, expect it closed, second device still open */
|
||||||
dev_fd = libevdev_get_fd(dev);
|
dev_fd = libevdev_get_fd(dev);
|
||||||
|
|
@ -81,6 +66,9 @@ START_TEST(test_revoke)
|
||||||
}
|
}
|
||||||
ck_assert_msg(rc == 0, "Failed to revoke device: %s", strerror(errno));
|
ck_assert_msg(rc == 0, "Failed to revoke device: %s", strerror(errno));
|
||||||
|
|
||||||
|
uinput_device_event(uidev, EV_REL, REL_X, 1);
|
||||||
|
uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
|
||||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1);
|
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1);
|
||||||
ck_assert_int_eq(rc, -ENODEV);
|
ck_assert_int_eq(rc, -ENODEV);
|
||||||
|
|
||||||
|
|
@ -160,26 +148,13 @@ out:
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
TEST_SUITE_ROOT_PRIVILEGES(kernel)
|
||||||
{
|
{
|
||||||
SRunner *sr;
|
Suite *s = suite_create("kernel");
|
||||||
Suite *s;
|
|
||||||
TCase *tc;
|
|
||||||
int failed;
|
|
||||||
|
|
||||||
s = suite_create("kernel tests");
|
add_test(s, test_revoke);
|
||||||
|
add_test(s, test_revoke_invalid);
|
||||||
|
add_test(s, test_revoke_fail_after);
|
||||||
|
|
||||||
tc = tcase_create("EVIOCREVOKE");
|
return s;
|
||||||
tcase_add_test(tc, test_revoke);
|
|
||||||
tcase_add_test(tc, test_revoke_invalid);
|
|
||||||
tcase_add_test(tc, test_revoke_fail_after);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
sr = srunner_create(s);
|
|
||||||
srunner_run_all(sr, CK_NORMAL);
|
|
||||||
|
|
||||||
failed = srunner_ntests_failed(sr);
|
|
||||||
srunner_free(sr);
|
|
||||||
|
|
||||||
return failed;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -117,6 +100,14 @@ START_TEST(test_event_codes)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
/* Force feedback events are not supported by FreeBSD */
|
||||||
|
if (*evbit == EV_FF) {
|
||||||
|
evbit++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
max = libevdev_event_type_get_max(*evbit);
|
max = libevdev_event_type_get_max(*evbit);
|
||||||
|
|
||||||
for (code = 1; code < max; code += 10) {
|
for (code = 1; code < max; code += 10) {
|
||||||
|
|
@ -125,10 +116,11 @@ START_TEST(test_event_codes)
|
||||||
test_create_abs_device(&uidev, &dev,
|
test_create_abs_device(&uidev, &dev,
|
||||||
1, &abs,
|
1, &abs,
|
||||||
-1);
|
-1);
|
||||||
} else
|
} else {
|
||||||
test_create_device(&uidev, &dev,
|
test_create_device(&uidev, &dev,
|
||||||
*evbit, code,
|
*evbit, code,
|
||||||
-1);
|
-1);
|
||||||
|
}
|
||||||
|
|
||||||
ck_assert_msg(libevdev_has_event_type(dev, *evbit), "for event type %d\n", *evbit);
|
ck_assert_msg(libevdev_has_event_type(dev, *evbit), "for event type %d\n", *evbit);
|
||||||
ck_assert_msg(libevdev_has_event_code(dev, *evbit, code), "for type %d code %d", *evbit, code);
|
ck_assert_msg(libevdev_has_event_code(dev, *evbit, code), "for type %d code %d", *evbit, code);
|
||||||
|
|
@ -249,7 +241,7 @@ START_TEST(test_input_props)
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
int rc, i;
|
int rc, i;
|
||||||
struct input_absinfo abs = {0, 0, 2, 0, 0};
|
struct input_absinfo abs = { .value = 0, .minimum = 0, .maximum = 2};
|
||||||
|
|
||||||
uidev = uinput_device_new(TEST_DEVICE_NAME);
|
uidev = uinput_device_new(TEST_DEVICE_NAME);
|
||||||
rc = uinput_device_set_abs_bit(uidev, ABS_X, &abs);
|
rc = uinput_device_set_abs_bit(uidev, ABS_X, &abs);
|
||||||
|
|
@ -282,7 +274,7 @@ START_TEST(test_set_input_props)
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
int rc, fd;
|
int rc, fd;
|
||||||
struct input_absinfo abs = {0, 0, 2, 0, 0};
|
struct input_absinfo abs = { .value = 0, .minimum = 0, .maximum = 2};
|
||||||
|
|
||||||
dev = libevdev_new();
|
dev = libevdev_new();
|
||||||
ck_assert_int_eq(libevdev_enable_property(dev, INPUT_PROP_MAX + 1), -1);
|
ck_assert_int_eq(libevdev_enable_property(dev, INPUT_PROP_MAX + 1), -1);
|
||||||
|
|
@ -305,6 +297,13 @@ START_TEST(test_set_input_props)
|
||||||
ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_DIRECT), 0);
|
ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_DIRECT), 0);
|
||||||
ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_BUTTONPAD), 1);
|
ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_BUTTONPAD), 1);
|
||||||
|
|
||||||
|
/* Test disabling the properties too */
|
||||||
|
ck_assert_int_eq(libevdev_disable_property(dev, INPUT_PROP_MAX + 1), -1);
|
||||||
|
ck_assert_int_eq(libevdev_disable_property(dev, INPUT_PROP_DIRECT), 0);
|
||||||
|
ck_assert_int_eq(libevdev_disable_property(dev, INPUT_PROP_BUTTONPAD), 0);
|
||||||
|
ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_DIRECT), 0);
|
||||||
|
ck_assert_int_eq(libevdev_has_property(dev, INPUT_PROP_BUTTONPAD), 0);
|
||||||
|
|
||||||
uinput_device_free(uidev);
|
uinput_device_free(uidev);
|
||||||
libevdev_free(dev);
|
libevdev_free(dev);
|
||||||
}
|
}
|
||||||
|
|
@ -318,12 +317,14 @@ START_TEST(test_slot_init_value)
|
||||||
const int nabs = 6;
|
const int nabs = 6;
|
||||||
int i;
|
int i;
|
||||||
int fd;
|
int fd;
|
||||||
struct input_absinfo abs[] = { { ABS_X, 0, 1000 },
|
struct input_absinfo abs[] = {
|
||||||
{ ABS_Y, 0, 1000 },
|
{ .value = ABS_X, .minimum = 0, .maximum = 1000 },
|
||||||
{ ABS_MT_POSITION_X, 0, 1000 },
|
{ .value = ABS_Y, .minimum = 0, .maximum = 1000 },
|
||||||
{ ABS_MT_POSITION_Y, 0, 1000 },
|
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 1000 },
|
||||||
{ ABS_MT_TRACKING_ID, -1, 2 },
|
{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 1000 },
|
||||||
{ ABS_MT_SLOT, 0, 1 }};
|
{ .value = ABS_MT_TRACKING_ID, .minimum = -1, .maximum = 2 },
|
||||||
|
{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = 1 }
|
||||||
|
};
|
||||||
|
|
||||||
uidev = uinput_device_new(TEST_DEVICE_NAME);
|
uidev = uinput_device_new(TEST_DEVICE_NAME);
|
||||||
|
|
||||||
|
|
@ -371,10 +372,12 @@ START_TEST(test_no_slots)
|
||||||
{
|
{
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
struct input_absinfo abs[] = { { ABS_X, 0, 2 },
|
struct input_absinfo abs[] = {
|
||||||
{ ABS_Y, 0, 2 },
|
{ .value = ABS_X, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_POSITION_X, 0, 2 },
|
{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_POSITION_Y, 0, 2 }};
|
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
|
||||||
|
{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 }
|
||||||
|
};
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev, 4, abs,
|
test_create_abs_device(&uidev, &dev, 4, abs,
|
||||||
-1);
|
-1);
|
||||||
|
|
@ -392,11 +395,13 @@ START_TEST(test_slot_number)
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
const int nslots = 4;
|
const int nslots = 4;
|
||||||
struct input_absinfo abs[] = { { ABS_X, 0, 2 },
|
struct input_absinfo abs[] = {
|
||||||
{ ABS_Y, 0, 2 },
|
{ .value = ABS_X, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_POSITION_X, 0, 2 },
|
{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_POSITION_Y, 0, 2 },
|
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_SLOT, 0, nslots - 1 }};
|
{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 },
|
||||||
|
{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = nslots - 1 }
|
||||||
|
};
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev, 5, abs,
|
test_create_abs_device(&uidev, &dev, 5, abs,
|
||||||
-1);
|
-1);
|
||||||
|
|
@ -415,12 +420,14 @@ START_TEST(test_invalid_mt_device)
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
const int nslots = 4;
|
const int nslots = 4;
|
||||||
int value;
|
int value;
|
||||||
struct input_absinfo abs[] = { { ABS_X, 0, 2 },
|
struct input_absinfo abs[] = {
|
||||||
{ ABS_Y, 0, 2 },
|
{ .value = ABS_X, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_POSITION_X, 0, 2 },
|
{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_POSITION_Y, 0, 2 },
|
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_SLOT - 1, 0, 2 },
|
{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 },
|
||||||
{ ABS_MT_SLOT, 0, nslots - 1 }};
|
{ .value = ABS_MT_SLOT - 1, .minimum = 0, .maximum = 2 },
|
||||||
|
{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = nslots - 1 }
|
||||||
|
};
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev, 6, abs,
|
test_create_abs_device(&uidev, &dev, 6, abs,
|
||||||
-1);
|
-1);
|
||||||
|
|
@ -732,7 +739,7 @@ START_TEST(test_device_enable_bit)
|
||||||
{
|
{
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev, *dev2;
|
struct libevdev *dev, *dev2;
|
||||||
struct input_absinfo abs = {ABS_X, 0, 2};
|
struct input_absinfo abs = { .value = ABS_X, .minimum = 0, .maximum = 2 };
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev, 1, &abs,
|
test_create_abs_device(&uidev, &dev, 1, &abs,
|
||||||
|
|
@ -776,7 +783,7 @@ START_TEST(test_device_enable_bit_invalid)
|
||||||
{
|
{
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
struct input_absinfo abs = {ABS_X, 0, 1};
|
struct input_absinfo abs = { .value = ABS_X, .minimum = 0, .maximum = 1 };
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev, 1, &abs,
|
test_create_abs_device(&uidev, &dev, 1, &abs,
|
||||||
-1);
|
-1);
|
||||||
|
|
@ -802,7 +809,10 @@ START_TEST(test_device_disable_bit)
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev, *dev2;
|
struct libevdev *dev, *dev2;
|
||||||
int rc;
|
int rc;
|
||||||
struct input_absinfo abs[2] = {{ABS_X, 0, 1}, {ABS_Y, 0, 1}};
|
struct input_absinfo abs[2] = {
|
||||||
|
{ .value = ABS_X, .minimum = 0, .maximum = 1 },
|
||||||
|
{ .value = ABS_Y, .minimum = 0, .maximum = 1 },
|
||||||
|
};
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev,
|
test_create_abs_device(&uidev, &dev,
|
||||||
2, abs,
|
2, abs,
|
||||||
|
|
@ -848,7 +858,7 @@ START_TEST(test_device_disable_bit_invalid)
|
||||||
{
|
{
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
struct input_absinfo abs = {ABS_X, 0, 1};
|
struct input_absinfo abs = { .value = ABS_X, .minimum = 0, .maximum = 1 };
|
||||||
|
|
||||||
test_create_abs_device(&uidev, &dev, 1, &abs, -1);
|
test_create_abs_device(&uidev, &dev, 1, &abs, -1);
|
||||||
|
|
||||||
|
|
@ -1142,61 +1152,44 @@ START_TEST(test_led_same)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
Suite *
|
TEST_SUITE_ROOT_PRIVILEGES(has_events)
|
||||||
libevdev_has_event_test(void)
|
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("libevdev_has_event tests");
|
Suite *s = suite_create("libevdev_has_event tests");
|
||||||
|
|
||||||
TCase *tc = tcase_create("event type");
|
add_test(s, test_ev_bit_limits);
|
||||||
tcase_add_test(tc, test_ev_bit_limits);
|
add_test(s, test_has_ev_bit);
|
||||||
tcase_add_test(tc, test_has_ev_bit);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("event codes");
|
add_test(s, test_event_codes);
|
||||||
tcase_add_test(tc, test_event_codes);
|
add_test(s, test_event_code_limits);
|
||||||
tcase_add_test(tc, test_event_code_limits);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("ev_rep");
|
add_test(s, test_ev_rep);
|
||||||
tcase_add_test(tc, test_ev_rep);
|
add_test(s, test_ev_rep_values);
|
||||||
tcase_add_test(tc, test_ev_rep_values);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("input properties");
|
add_test(s, test_input_props);
|
||||||
tcase_add_test(tc, test_input_props);
|
add_test(s, test_set_input_props);
|
||||||
tcase_add_test(tc, test_set_input_props);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("multitouch info");
|
add_test(s, test_no_slots);
|
||||||
tcase_add_test(tc, test_no_slots);
|
add_test(s, test_slot_number);
|
||||||
tcase_add_test(tc, test_slot_number);
|
add_test(s, test_slot_init_value);
|
||||||
tcase_add_test(tc, test_slot_init_value);
|
add_test(s, test_invalid_mt_device);
|
||||||
tcase_add_test(tc, test_invalid_mt_device);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("device info");
|
add_test(s, test_device_name);
|
||||||
tcase_add_test(tc, test_device_name);
|
add_test(s, test_device_set_name);
|
||||||
tcase_add_test(tc, test_device_set_name);
|
add_test(s, test_device_set_ids);
|
||||||
tcase_add_test(tc, test_device_set_ids);
|
add_test(s, test_device_get_abs_info);
|
||||||
tcase_add_test(tc, test_device_get_abs_info);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("device bit manipulation");
|
add_test(s, test_device_set_abs);
|
||||||
tcase_add_test(tc, test_device_set_abs);
|
add_test(s, test_device_enable_bit);
|
||||||
tcase_add_test(tc, test_device_enable_bit);
|
add_test(s, test_device_enable_bit_invalid);
|
||||||
tcase_add_test(tc, test_device_enable_bit_invalid);
|
add_test(s, test_device_disable_bit);
|
||||||
tcase_add_test(tc, test_device_disable_bit);
|
add_test(s, test_device_disable_bit_invalid);
|
||||||
tcase_add_test(tc, test_device_disable_bit_invalid);
|
add_test(s, test_device_kernel_change_axis);
|
||||||
tcase_add_test(tc, test_device_kernel_change_axis);
|
add_test(s, test_device_kernel_change_axis_invalid);
|
||||||
tcase_add_test(tc, test_device_kernel_change_axis_invalid);
|
add_test(s, test_device_kernel_set_abs_invalid_fd);
|
||||||
tcase_add_test(tc, test_device_kernel_set_abs_invalid_fd);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("led manipulation");
|
add_test(s, test_led_valid);
|
||||||
tcase_add_test(tc, test_led_valid);
|
add_test(s, test_led_invalid);
|
||||||
tcase_add_test(tc, test_led_invalid);
|
add_test(s, test_led_same);
|
||||||
tcase_add_test(tc, test_led_same);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -468,10 +451,98 @@ START_TEST(test_device_grab_invalid_fd)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_device_grab_change_fd)
|
||||||
|
{
|
||||||
|
struct libevdev_uinput *uidev;
|
||||||
|
struct libevdev *dev, *other;
|
||||||
|
struct input_event e;
|
||||||
|
int rc;
|
||||||
|
int other_fd;
|
||||||
|
int dev_fd;
|
||||||
|
|
||||||
|
dev = libevdev_new();
|
||||||
|
libevdev_set_name(dev, "libevdev test device");
|
||||||
|
libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
|
||||||
|
libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
|
||||||
|
libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
|
||||||
|
|
||||||
|
rc = libevdev_uinput_create_from_device(dev,
|
||||||
|
LIBEVDEV_UINPUT_OPEN_MANAGED,
|
||||||
|
&uidev);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
libevdev_free(dev);
|
||||||
|
|
||||||
|
dev_fd = open(libevdev_uinput_get_devnode(uidev),
|
||||||
|
O_RDONLY|O_NONBLOCK);
|
||||||
|
ck_assert_int_ne(dev_fd, -1);
|
||||||
|
rc = libevdev_new_from_fd(dev_fd, &dev);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
other_fd = open(libevdev_uinput_get_devnode(uidev),
|
||||||
|
O_RDONLY|O_NONBLOCK);
|
||||||
|
ck_assert_int_ne(other_fd, -1);
|
||||||
|
rc = libevdev_new_from_fd(other_fd, &other);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
/* check we're getting the events before the grab */
|
||||||
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
||||||
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, -EAGAIN);
|
||||||
|
|
||||||
|
/* no events after the grab */
|
||||||
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
||||||
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, -EAGAIN);
|
||||||
|
|
||||||
|
/* swapping the fd removes the grab */
|
||||||
|
close(dev_fd);
|
||||||
|
dev_fd = open(libevdev_uinput_get_devnode(uidev),
|
||||||
|
O_RDONLY|O_NONBLOCK);
|
||||||
|
ck_assert_int_ne(dev_fd, -1);
|
||||||
|
rc = libevdev_change_fd(dev, dev_fd);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
/* check we're getting the events again */
|
||||||
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
||||||
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, -EAGAIN);
|
||||||
|
|
||||||
|
/* no events after the grab */
|
||||||
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
||||||
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
||||||
|
ck_assert_int_eq(rc, -EAGAIN);
|
||||||
|
|
||||||
|
libevdev_uinput_destroy(uidev);
|
||||||
|
libevdev_free(dev);
|
||||||
|
libevdev_free(other);
|
||||||
|
close(dev_fd);
|
||||||
|
close(other_fd);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_set_clock_id)
|
START_TEST(test_set_clock_id)
|
||||||
{
|
{
|
||||||
struct uinput_device* uidev;
|
struct uinput_device* uidev;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
|
int clockid;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
test_create_device(&uidev, &dev,
|
test_create_device(&uidev, &dev,
|
||||||
|
|
@ -490,7 +561,13 @@ START_TEST(test_set_clock_id)
|
||||||
rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
|
rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
|
||||||
ck_assert_int_eq(rc, 0);
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC_RAW);
|
#ifdef __FreeBSD__
|
||||||
|
clockid = CLOCK_MONOTONIC_FAST;
|
||||||
|
#else
|
||||||
|
clockid = CLOCK_MONOTONIC_RAW;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rc = libevdev_set_clock_id(dev, clockid);
|
||||||
ck_assert_int_eq(rc, -EINVAL);
|
ck_assert_int_eq(rc, -EINVAL);
|
||||||
|
|
||||||
uinput_device_free(uidev);
|
uinput_device_free(uidev);
|
||||||
|
|
@ -575,19 +652,19 @@ START_TEST(test_clock_id_events)
|
||||||
ck_assert_int_eq(ev1.code, ev2.code);
|
ck_assert_int_eq(ev1.code, ev2.code);
|
||||||
ck_assert_int_eq(ev1.value, ev2.value);
|
ck_assert_int_eq(ev1.value, ev2.value);
|
||||||
|
|
||||||
t1 = ev1.time.tv_sec * 1000000LL + ev1.time.tv_usec;
|
t1 = ev1.input_event_sec * 1000000LL + ev1.input_event_usec;
|
||||||
t2 = ev2.time.tv_sec * 1000000LL + ev2.time.tv_usec;
|
t2 = ev2.input_event_sec * 1000000LL + ev2.input_event_usec;
|
||||||
ck_assert_int_ne(t1, t2);
|
ck_assert_int_ne(t1, t2);
|
||||||
|
|
||||||
ck_assert_int_ge(ev1.time.tv_sec, t1_real.tv_sec);
|
ck_assert_int_ge(ev1.input_event_sec, t1_real.tv_sec);
|
||||||
ck_assert_int_ge(ev1.time.tv_usec, t1_real.tv_nsec/1000);
|
ck_assert_int_ge(ev1.input_event_usec, t1_real.tv_nsec/1000);
|
||||||
ck_assert_int_le(ev1.time.tv_sec, t2_real.tv_sec);
|
ck_assert_int_le(ev1.input_event_sec, t2_real.tv_sec);
|
||||||
ck_assert_int_le(ev1.time.tv_usec, t2_real.tv_nsec/1000);
|
ck_assert_int_le(ev1.input_event_usec, t2_real.tv_nsec/1000);
|
||||||
|
|
||||||
ck_assert_int_ge(ev2.time.tv_sec, t1_mono.tv_sec);
|
ck_assert_int_ge(ev2.input_event_sec, t1_mono.tv_sec);
|
||||||
ck_assert_int_ge(ev2.time.tv_usec, t1_mono.tv_nsec/1000);
|
ck_assert_int_ge(ev2.input_event_usec, t1_mono.tv_nsec/1000);
|
||||||
ck_assert_int_le(ev2.time.tv_sec, t2_mono.tv_sec);
|
ck_assert_int_le(ev2.input_event_sec, t2_mono.tv_sec);
|
||||||
ck_assert_int_le(ev2.time.tv_usec, t2_mono.tv_nsec/1000);
|
ck_assert_int_le(ev2.input_event_usec, t2_mono.tv_nsec/1000);
|
||||||
|
|
||||||
uinput_device_free(uidev);
|
uinput_device_free(uidev);
|
||||||
libevdev_free(dev);
|
libevdev_free(dev);
|
||||||
|
|
@ -596,42 +673,32 @@ START_TEST(test_clock_id_events)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
Suite *
|
TEST_SUITE_ROOT_PRIVILEGES(libevdev_init_test)
|
||||||
libevdev_init_test(void)
|
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("libevdev init tests");
|
Suite *s = suite_create("libevdev init tests");
|
||||||
|
|
||||||
TCase *tc = tcase_create("device init");
|
add_test(s, test_new_device);
|
||||||
tcase_add_test(tc, test_new_device);
|
add_test(s, test_free_device);
|
||||||
tcase_add_test(tc, test_free_device);
|
add_test(s, test_init_from_invalid_fd);
|
||||||
tcase_add_test(tc, test_init_from_invalid_fd);
|
add_test(s, test_init_and_change_fd);
|
||||||
tcase_add_test(tc, test_init_and_change_fd);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("log init");
|
add_test(s, test_log_init);
|
||||||
tcase_add_test(tc, test_log_init);
|
add_test(s, test_log_priority);
|
||||||
tcase_add_test(tc, test_log_priority);
|
add_test(s, test_log_set_get_priority);
|
||||||
tcase_add_test(tc, test_log_set_get_priority);
|
add_test(s, test_log_default_priority);
|
||||||
tcase_add_test(tc, test_log_default_priority);
|
add_test(s, test_log_data);
|
||||||
tcase_add_test(tc, test_log_data);
|
add_test(s, test_device_log_init);
|
||||||
tcase_add_test(tc, test_device_log_init);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("device fd init");
|
add_test(s, test_device_init);
|
||||||
tcase_add_test(tc, test_device_init);
|
add_test(s, test_device_init_from_fd);
|
||||||
tcase_add_test(tc, test_device_init_from_fd);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("device grab");
|
add_test(s, test_device_grab);
|
||||||
tcase_add_test(tc, test_device_grab);
|
add_test(s, test_device_grab_invalid_fd);
|
||||||
tcase_add_test(tc, test_device_grab_invalid_fd);
|
add_test(s, test_device_grab_change_fd);
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("clock id");
|
add_test(s, test_set_clock_id);
|
||||||
tcase_add_test(tc, test_set_clock_id);
|
add_test(s, test_set_clock_id_invalid_fd);
|
||||||
tcase_add_test(tc, test_set_clock_id_invalid_fd);
|
add_test(s, test_clock_id_events);
|
||||||
tcase_add_test(tc, test_clock_id_events);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
105
test/test-main.c
105
test/test-main.c
|
|
@ -1,48 +1,33 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <libevdev/libevdev.h>
|
#include <libevdev/libevdev.h>
|
||||||
|
|
||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
||||||
extern Suite *event_name_suite(void);
|
|
||||||
extern Suite *event_code_suite(void);
|
|
||||||
extern Suite *libevdev_init_test(void);
|
|
||||||
extern Suite *queue_suite(void);
|
|
||||||
extern Suite *libevdev_has_event_test(void);
|
|
||||||
extern Suite *libevdev_events(void);
|
|
||||||
extern Suite *uinput_suite(void);
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
is_debugger_attached(void)
|
is_debugger_attached(void)
|
||||||
{
|
{
|
||||||
|
int rc = 1;
|
||||||
|
/*
|
||||||
|
* FreeBSD does not support PTRACE_ATTACH, disable attaching a debugger
|
||||||
|
* on FreeBSD by skipping the rest of the function and just return 1.
|
||||||
|
*/
|
||||||
|
#ifndef __FreeBSD__
|
||||||
int status;
|
int status;
|
||||||
int rc;
|
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
|
|
@ -55,35 +40,75 @@ is_debugger_attached(void)
|
||||||
ptrace(PTRACE_CONT, NULL, NULL);
|
ptrace(PTRACE_CONT, NULL, NULL);
|
||||||
ptrace(PTRACE_DETACH, ppid, NULL, NULL);
|
ptrace(PTRACE_DETACH, ppid, NULL, NULL);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else
|
}
|
||||||
rc = 1;
|
|
||||||
_exit(rc);
|
_exit(rc);
|
||||||
} else {
|
} else {
|
||||||
waitpid(pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
rc = WEXITSTATUS(status);
|
rc = WEXITSTATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* !__FreeBSD__ */
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
static bool
|
||||||
|
device_nodes_exist(void)
|
||||||
{
|
{
|
||||||
|
struct stat st;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = stat("/dev/uinput", &st);
|
||||||
|
if (rc == -1 && errno == ENOENT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rc = stat("/dev/input", &st);
|
||||||
|
if (rc == -1 && errno == ENOENT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Any issues but ENOENT we just let the test suite blow up later */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const struct libevdev_test __start_test_section, __stop_test_section;
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
const struct libevdev_test *t;
|
||||||
|
const struct rlimit corelimit = {0, 0};
|
||||||
int failed;
|
int failed;
|
||||||
|
|
||||||
|
for (t = &__start_test_section; t < &__stop_test_section; t++) {
|
||||||
|
if (t->needs_root_privileges) {
|
||||||
|
if (getenv("LIBEVDEV_SKIP_ROOT_TESTS"))
|
||||||
|
return 77;
|
||||||
|
|
||||||
|
if (getuid() != 0) {
|
||||||
|
fprintf(stderr, "This test needs to run as root\n");
|
||||||
|
return 77;
|
||||||
|
}
|
||||||
|
if (!device_nodes_exist()) {
|
||||||
|
fprintf(stderr, "This test needs /dev/input and /dev/uinput to exist\n");
|
||||||
|
return 77;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (is_debugger_attached())
|
if (is_debugger_attached())
|
||||||
setenv("CK_FORK", "no", 0);
|
setenv("CK_FORK", "no", 0);
|
||||||
|
|
||||||
|
if (setrlimit(RLIMIT_CORE, &corelimit) != 0)
|
||||||
|
perror("WARNING: Core dumps not disabled. Reason");
|
||||||
|
|
||||||
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
||||||
|
|
||||||
Suite *s = libevdev_has_event_test();
|
SRunner *sr = srunner_create(NULL);
|
||||||
SRunner *sr = srunner_create(s);
|
for (t = &__start_test_section; t < &__stop_test_section; t++) {
|
||||||
srunner_add_suite(sr, libevdev_events());
|
srunner_add_suite(sr, t->setup());
|
||||||
srunner_add_suite(sr, libevdev_init_test());
|
}
|
||||||
srunner_add_suite(sr, queue_suite());
|
|
||||||
srunner_add_suite(sr, event_name_suite());
|
srunner_run_all(sr, CK_ENV);
|
||||||
srunner_add_suite(sr, event_code_suite());
|
|
||||||
srunner_add_suite(sr, uinput_suite());
|
|
||||||
srunner_run_all(sr, CK_NORMAL);
|
|
||||||
|
|
||||||
failed = srunner_ntests_failed(sr);
|
failed = srunner_ntests_failed(sr);
|
||||||
srunner_free(sr);
|
srunner_free(sr);
|
||||||
|
|
|
||||||
21
test/test-static-symbols-leak.sh
Executable file
21
test/test-static-symbols-leak.sh
Executable file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Hack to check for leaking symbols in the static library.
|
||||||
|
# See https://bugs.freedesktop.org/show_bug.cgi?id=82785
|
||||||
|
# Note the spaces in the expressions! After the first grep, each line
|
||||||
|
# is " T symbol_name"
|
||||||
|
|
||||||
|
test -z "$RUNNING_ON_VALGRIND" || exit 77
|
||||||
|
|
||||||
|
builddir="$1"
|
||||||
|
|
||||||
|
test -f "$builddir/test-static-link" || (echo "Unable to find test file" && exit 1)
|
||||||
|
nm --extern-only "$builddir/test-static-link" |
|
||||||
|
grep -o -e " T .*" | \
|
||||||
|
grep -v -e " main\$" \
|
||||||
|
-e " atexit" \
|
||||||
|
-e " mangle_path" \
|
||||||
|
-e " *gcov.*" \
|
||||||
|
-e " _.*" \
|
||||||
|
-e " libevdev_*" && \
|
||||||
|
echo "Leaking symbols found" && exit 1 || exit 0
|
||||||
|
|
@ -1,26 +1,9 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -69,7 +52,7 @@ START_TEST(test_uinput_create_device)
|
||||||
if (max == -1)
|
if (max == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (code = 0; code < max; code++) {
|
for (code = 0; code < (unsigned int)max; code++) {
|
||||||
ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
|
ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
|
||||||
libevdev_has_event_code(dev2, type, code));
|
libevdev_has_event_code(dev2, type, code));
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +133,7 @@ START_TEST(test_uinput_create_device_from_fd)
|
||||||
if (max == -1)
|
if (max == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (code = 0; code < max; code++) {
|
for (code = 0; code < (unsigned int)max; code++) {
|
||||||
ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
|
ck_assert_int_eq(libevdev_has_event_code(dev, type, code),
|
||||||
libevdev_has_event_code(dev2, type, code));
|
libevdev_has_event_code(dev2, type, code));
|
||||||
}
|
}
|
||||||
|
|
@ -164,6 +147,93 @@ START_TEST(test_uinput_create_device_from_fd)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
START_TEST(test_uinput_check_devnode_bsd)
|
||||||
|
{
|
||||||
|
struct libevdev *dev;
|
||||||
|
struct libevdev_uinput *uidev, *uidev2;
|
||||||
|
const char *devnode, *devnode2;
|
||||||
|
int fd, fd2;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
dev = libevdev_new();
|
||||||
|
ck_assert(dev != NULL);
|
||||||
|
libevdev_set_name(dev, TEST_DEVICE_NAME);
|
||||||
|
libevdev_enable_event_type(dev, EV_SYN);
|
||||||
|
libevdev_enable_event_type(dev, EV_REL);
|
||||||
|
libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
|
||||||
|
libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
|
||||||
|
|
||||||
|
fd = open(UINPUT_NODE, O_RDWR);
|
||||||
|
ck_assert_int_gt(fd, -1);
|
||||||
|
fd2 = open(UINPUT_NODE, O_RDWR);
|
||||||
|
ck_assert_int_gt(fd2, -1);
|
||||||
|
|
||||||
|
rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
/* create a second one */
|
||||||
|
libevdev_set_name(dev, TEST_DEVICE_NAME " 2");
|
||||||
|
rc = libevdev_uinput_create_from_device(dev, fd2, &uidev2);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
devnode = libevdev_uinput_get_devnode(uidev);
|
||||||
|
ck_assert(devnode != NULL);
|
||||||
|
|
||||||
|
/* get syspath twice returns same pointer */
|
||||||
|
devnode2 = libevdev_uinput_get_devnode(uidev);
|
||||||
|
ck_assert(devnode == devnode2);
|
||||||
|
|
||||||
|
/* second dev has different devnode */
|
||||||
|
devnode2 = libevdev_uinput_get_devnode(uidev2);
|
||||||
|
ck_assert(strcmp(devnode, devnode2) != 0);
|
||||||
|
|
||||||
|
libevdev_uinput_destroy(uidev2);
|
||||||
|
libevdev_uinput_destroy(uidev);
|
||||||
|
|
||||||
|
close(fd2);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
libevdev_free(dev);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_uinput_check_syspath_bsd)
|
||||||
|
{
|
||||||
|
struct libevdev *dev;
|
||||||
|
struct libevdev_uinput *uidev;
|
||||||
|
const char *syspath;
|
||||||
|
int fd;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
dev = libevdev_new();
|
||||||
|
ck_assert(dev != NULL);
|
||||||
|
libevdev_set_name(dev, TEST_DEVICE_NAME);
|
||||||
|
libevdev_enable_event_type(dev, EV_SYN);
|
||||||
|
libevdev_enable_event_type(dev, EV_REL);
|
||||||
|
libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
|
||||||
|
libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
|
||||||
|
|
||||||
|
fd = open(UINPUT_NODE, O_RDWR);
|
||||||
|
ck_assert_int_gt(fd, -1);
|
||||||
|
|
||||||
|
rc = libevdev_uinput_create_from_device(dev, fd, &uidev);
|
||||||
|
ck_assert_int_eq(rc, 0);
|
||||||
|
|
||||||
|
syspath = libevdev_uinput_get_syspath(uidev);
|
||||||
|
/* FreeBSD should always return NULL for libevdev_unput_get_syspath() */
|
||||||
|
ck_assert(syspath == NULL);
|
||||||
|
|
||||||
|
libevdev_uinput_destroy(uidev);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
libevdev_free(dev);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
#else /* !__FreeBSD__ */
|
||||||
|
|
||||||
START_TEST(test_uinput_check_syspath_time)
|
START_TEST(test_uinput_check_syspath_time)
|
||||||
{
|
{
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
|
|
@ -269,6 +339,8 @@ START_TEST(test_uinput_check_syspath_name)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
#endif /* __FreeBSD __ */
|
||||||
|
|
||||||
START_TEST(test_uinput_events)
|
START_TEST(test_uinput_events)
|
||||||
{
|
{
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
|
|
@ -368,26 +440,24 @@ START_TEST(test_uinput_properties)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
Suite *
|
TEST_SUITE_ROOT_PRIVILEGES(uinput_suite)
|
||||||
uinput_suite(void)
|
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("libevdev uinput device tests");
|
Suite *s = suite_create("libevdev uinput device tests");
|
||||||
|
|
||||||
TCase *tc = tcase_create("device creation");
|
add_test(s, test_uinput_create_device);
|
||||||
tcase_add_test(tc, test_uinput_create_device);
|
add_test(s, test_uinput_create_device_invalid);
|
||||||
tcase_add_test(tc, test_uinput_create_device_invalid);
|
add_test(s, test_uinput_create_device_from_fd);
|
||||||
tcase_add_test(tc, test_uinput_create_device_from_fd);
|
#ifdef __FreeBSD__
|
||||||
tcase_add_test(tc, test_uinput_check_syspath_time);
|
add_test(s, test_uinput_check_devnode_bsd);
|
||||||
tcase_add_test(tc, test_uinput_check_syspath_name);
|
add_test(s, test_uinput_check_syspath_bsd);
|
||||||
suite_add_tcase(s, tc);
|
#else
|
||||||
|
add_test(s, test_uinput_check_syspath_time);
|
||||||
|
add_test(s, test_uinput_check_syspath_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
tc = tcase_create("device events");
|
add_test(s, test_uinput_events);
|
||||||
tcase_add_test(tc, test_uinput_events);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
tc = tcase_create("device properties");
|
add_test(s, test_uinput_properties);
|
||||||
tcase_add_test(tc, test_uinput_properties);
|
|
||||||
suite_add_tcase(s, tc);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,10 @@
|
||||||
fun:ioctl
|
fun:ioctl
|
||||||
fun:test_revoke*
|
fun:test_revoke*
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
<bash_memleak>
|
||||||
|
Memcheck:Leak
|
||||||
|
...
|
||||||
|
fun:reader_loop
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
noinst_PROGRAMS = libevdev-events
|
noinst_PROGRAMS = libevdev-events libevdev-list-codes
|
||||||
bin_PROGRAMS = \
|
bin_PROGRAMS = \
|
||||||
touchpad-edge-detector \
|
touchpad-edge-detector \
|
||||||
mouse-dpi-tool \
|
mouse-dpi-tool \
|
||||||
|
|
@ -10,6 +10,9 @@ libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
|
||||||
libevdev_events_SOURCES = libevdev-events.c
|
libevdev_events_SOURCES = libevdev-events.c
|
||||||
libevdev_events_LDADD = $(libevdev_ldadd)
|
libevdev_events_LDADD = $(libevdev_ldadd)
|
||||||
|
|
||||||
|
libevdev_list_codes_SOURCES = libevdev-list-codes.c
|
||||||
|
libevdev_list_codes_LDADD = $(libevdev_ldadd)
|
||||||
|
|
||||||
touchpad_edge_detector_SOURCES = touchpad-edge-detector.c
|
touchpad_edge_detector_SOURCES = touchpad-edge-detector.c
|
||||||
touchpad_edge_detector_LDADD = $(libevdev_ldadd)
|
touchpad_edge_detector_LDADD = $(libevdev_ldadd)
|
||||||
|
|
||||||
|
|
@ -18,4 +21,9 @@ mouse_dpi_tool_LDADD = $(libevdev_ldadd)
|
||||||
|
|
||||||
libevdev_tweak_device_SOURCES = libevdev-tweak-device.c
|
libevdev_tweak_device_SOURCES = libevdev-tweak-device.c
|
||||||
libevdev_tweak_device_LDADD = $(libevdev_ldadd)
|
libevdev_tweak_device_LDADD = $(libevdev_ldadd)
|
||||||
libevdev_tweak_device_MANS = libevdev-tweak-device.1
|
|
||||||
|
dist_man_MANS = \
|
||||||
|
libevdev-tweak-device.1 \
|
||||||
|
mouse-dpi-tool.1 \
|
||||||
|
touchpad-edge-detector.1 \
|
||||||
|
$(NULL)
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,20 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2013 Red Hat, Inc.
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/input.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <sys/types.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <linux/input.h>
|
|
||||||
|
|
||||||
#include "libevdev.h"
|
#include "libevdev/libevdev.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_abs_bits(struct libevdev *dev, int axis)
|
print_abs_bits(struct libevdev *dev, int axis)
|
||||||
|
|
@ -112,13 +95,13 @@ print_event(struct input_event *ev)
|
||||||
{
|
{
|
||||||
if (ev->type == EV_SYN)
|
if (ev->type == EV_SYN)
|
||||||
printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
|
printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
|
||||||
ev->time.tv_sec,
|
ev->input_event_sec,
|
||||||
ev->time.tv_usec,
|
ev->input_event_usec,
|
||||||
libevdev_event_type_get_name(ev->type));
|
libevdev_event_type_get_name(ev->type));
|
||||||
else
|
else
|
||||||
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
|
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
|
||||||
ev->time.tv_sec,
|
ev->input_event_sec,
|
||||||
ev->time.tv_usec,
|
ev->input_event_usec,
|
||||||
ev->type,
|
ev->type,
|
||||||
libevdev_event_type_get_name(ev->type),
|
libevdev_event_type_get_name(ev->type),
|
||||||
ev->code,
|
ev->code,
|
||||||
|
|
|
||||||
47
tools/libevdev-list-codes.c
Normal file
47
tools/libevdev-list-codes.c
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* Copyright © 2021 Red Hat, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Lists all event types and codes currently known by libevdev. */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include "libevdev/libevdev.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_event_codes(unsigned int type, unsigned int max)
|
||||||
|
{
|
||||||
|
const char *typestr = libevdev_event_type_get_name(type);
|
||||||
|
|
||||||
|
if (!typestr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf("- %s:\n", typestr);
|
||||||
|
|
||||||
|
for (unsigned int code = 0; code <= max; code++) {
|
||||||
|
const char *str = libevdev_event_code_get_name(type, code);
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
printf(" %d: %s\n", code, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
printf("codes:\n");
|
||||||
|
for (unsigned int type = 0; type <= EV_MAX; type++) {
|
||||||
|
int max = libevdev_event_type_get_max(type);
|
||||||
|
if (max == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
list_event_codes(type, (unsigned int)max);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1,46 +1,29 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2014 Red Hat, Inc.
|
* Copyright © 2014 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
|
||||||
* the above copyright notice appear in all copies and that both that copyright
|
|
||||||
* notice and this permission notice appear in supporting documentation, and
|
|
||||||
* that the name of the copyright holders not be used in advertising or
|
|
||||||
* publicity pertaining to distribution of the software without specific,
|
|
||||||
* written prior permission. The copyright holders make no representations
|
|
||||||
* about the suitability of this software for any purpose. It is provided "as
|
|
||||||
* is" without express or implied warranty.
|
|
||||||
*
|
|
||||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
||||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
||||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
||||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
|
||||||
* OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#include "config.h"
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <linux/input.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <sys/types.h>
|
||||||
#include <assert.h>
|
#include <unistd.h>
|
||||||
#include <linux/input.h>
|
|
||||||
|
|
||||||
#include "libevdev.h"
|
#include "libevdev/libevdev.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(const char *progname)
|
||||||
{
|
{
|
||||||
printf("%s --abs <axis> [--min min] [--max max] [--res res] [--fuzz fuzz] [--flat flat] /dev/input/eventXYZ\n"
|
printf("%s --abs <axis> [--min min] [--max max] [--res res] [--fuzz fuzz] [--flat flat] /dev/input/eventXYZ\n"
|
||||||
"\tChange the absinfo struct for the named axis\n"
|
"\tChange the absinfo struct for the named axis\n"
|
||||||
|
|
@ -48,9 +31,9 @@ usage(void)
|
||||||
"\tChange the x/y resolution on the given device\n"
|
"\tChange the x/y resolution on the given device\n"
|
||||||
"%s --led <led> --on|--off /dev/input/eventXYZ\n"
|
"%s --led <led> --on|--off /dev/input/eventXYZ\n"
|
||||||
"\tEnable or disable the named LED\n",
|
"\tEnable or disable the named LED\n",
|
||||||
program_invocation_short_name,
|
progname,
|
||||||
program_invocation_short_name,
|
progname,
|
||||||
program_invocation_short_name);
|
progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum mode {
|
enum mode {
|
||||||
|
|
@ -416,7 +399,7 @@ main(int argc, char **argv)
|
||||||
rc = EXIT_SUCCESS;
|
rc = EXIT_SUCCESS;
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case MODE_NONE:
|
case MODE_NONE:
|
||||||
usage();
|
usage(basename(argv[0]));
|
||||||
goto out;
|
goto out;
|
||||||
case MODE_ABS:
|
case MODE_ABS:
|
||||||
rc = parse_options_abs(argc, argv, &changes, &axis,
|
rc = parse_options_abs(argc, argv, &changes, &axis,
|
||||||
|
|
@ -440,7 +423,7 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
if (optind >= argc) {
|
if (optind >= argc) {
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
usage();
|
usage(basename(argv[0]));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
tools/mouse-dpi-tool.1
Normal file
18
tools/mouse-dpi-tool.1
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
.TH MOUSE-DPI-TOOL "1"
|
||||||
|
.SH NAME
|
||||||
|
mouse-dpi-tool \- mouse resolution estimation tool
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.BR mouse-dpi-tool " <\fIevdev device\fP>"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B mouse-dpi-tool
|
||||||
|
reads relative events (mouse movement events) and calculates the
|
||||||
|
distance covered and maximum frequency of the incoming events.
|
||||||
|
Combined with a measurement of the actual distance physically covered,
|
||||||
|
this allows the mouse's resolution to be estimated.
|
||||||
|
.PP
|
||||||
|
Some mouse devices provide dynamic frequencies, it is
|
||||||
|
recommended to measure multiple times to obtain the highest value.
|
||||||
|
.PP
|
||||||
|
.SH OPTIONS
|
||||||
|
.B mouse-dpi-tool
|
||||||
|
accepts no options.
|
||||||
|
|
@ -1,55 +1,41 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2014 Red Hat, Inc.
|
* Copyright © 2014 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software
|
|
||||||
* and its documentation for any purpose is hereby granted without
|
|
||||||
* fee, provided that the above copyright notice appear in all copies
|
|
||||||
* and that both that copyright notice and this permission notice
|
|
||||||
* appear in supporting documentation, and that the name of Red Hat
|
|
||||||
* not be used in advertising or publicity pertaining to distribution
|
|
||||||
* of the software without specific, written prior permission. Red
|
|
||||||
* Hat makes no representations about the suitability of this software
|
|
||||||
* for any purpose. It is provided "as is" without express or implied
|
|
||||||
* warranty.
|
|
||||||
*
|
|
||||||
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
||||||
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libevdev/libevdev.h>
|
|
||||||
#include <sys/signalfd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "libevdev/libevdev.h"
|
||||||
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
static int signalled = 0;
|
||||||
|
|
||||||
struct measurements {
|
struct measurements {
|
||||||
int distance;
|
int distance;
|
||||||
double frequency;
|
double max_frequency;
|
||||||
|
double *frequencies;
|
||||||
|
size_t frequencies_sz;
|
||||||
|
size_t nfrequencies;
|
||||||
uint64_t us;
|
uint64_t us;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
usage(void) {
|
usage(const char *progname) {
|
||||||
printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
|
printf("Usage: %s /dev/input/event0\n", progname);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("This tool reads relative events from the kernel and calculates\n"
|
printf("This tool reads relative events from the kernel and calculates\n"
|
||||||
"the distance covered and maximum frequency of the incoming events.\n"
|
"the distance covered and maximum frequency of the incoming events.\n"
|
||||||
|
|
@ -58,18 +44,27 @@ usage(void) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t
|
|
||||||
tv2us(const struct timeval *tv)
|
|
||||||
{
|
|
||||||
return tv->tv_sec * 1000000 + tv->tv_usec;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
get_frequency(double last, double current)
|
get_frequency(uint64_t last, uint64_t current)
|
||||||
{
|
{
|
||||||
return 1000000.0/(current - last);
|
return 1000000.0/(current - last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
push_frequency(struct measurements *m, double freq)
|
||||||
|
{
|
||||||
|
if (m->nfrequencies == m->frequencies_sz) {
|
||||||
|
m->frequencies_sz += 100;
|
||||||
|
m->frequencies = realloc(m->frequencies,
|
||||||
|
m->frequencies_sz * sizeof *m->frequencies);
|
||||||
|
if (!m->frequencies)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
m->frequencies[m->nfrequencies] = freq;
|
||||||
|
m->nfrequencies++;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
print_current_values(const struct measurements *m)
|
print_current_values(const struct measurements *m)
|
||||||
{
|
{
|
||||||
|
|
@ -89,7 +84,7 @@ print_current_values(const struct measurements *m)
|
||||||
progress = (progress + 1) % 4;
|
progress = (progress + 1) % 4;
|
||||||
|
|
||||||
printf("\rCovered distance in device units: %8d at frequency %3.1fHz %c",
|
printf("\rCovered distance in device units: %8d at frequency %3.1fHz %c",
|
||||||
abs(m->distance), m->frequency, status);
|
abs(m->distance), m->max_frequency, status);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -101,20 +96,23 @@ handle_event(struct measurements *m, const struct input_event *ev)
|
||||||
const int idle_reset = 3000000; /* us */
|
const int idle_reset = 3000000; /* us */
|
||||||
uint64_t last_us = m->us;
|
uint64_t last_us = m->us;
|
||||||
|
|
||||||
m->us = tv2us(&ev->time);
|
m->us = ev->input_event_sec * 1000000 + ev->input_event_usec;
|
||||||
|
|
||||||
/* reset after pause */
|
/* reset after pause */
|
||||||
if (last_us + idle_reset < m->us) {
|
if (last_us + idle_reset < m->us) {
|
||||||
m->frequency = 0.0;
|
m->max_frequency = 0.0;
|
||||||
m->distance = 0;
|
m->distance = 0;
|
||||||
} else {
|
} else {
|
||||||
double freq = get_frequency(last_us, m->us);
|
double freq = get_frequency(last_us, m->us);
|
||||||
m->frequency = max(freq, m->frequency);
|
push_frequency(m, freq);
|
||||||
|
m->max_frequency = max(freq, m->max_frequency);
|
||||||
return print_current_values(m);
|
return print_current_values(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (ev->type != EV_REL)
|
}
|
||||||
|
|
||||||
|
if (ev->type != EV_REL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch(ev->code) {
|
switch(ev->code) {
|
||||||
|
|
@ -126,26 +124,26 @@ handle_event(struct measurements *m, const struct input_event *ev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler(__attribute__((__unused__)) int signal)
|
||||||
|
{
|
||||||
|
signalled++;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mainloop(struct libevdev *dev, struct measurements *m) {
|
mainloop(struct libevdev *dev, struct measurements *m) {
|
||||||
struct pollfd fds[2];
|
struct pollfd fds;
|
||||||
sigset_t mask;
|
|
||||||
|
|
||||||
fds[0].fd = libevdev_get_fd(dev);
|
fds.fd = libevdev_get_fd(dev);
|
||||||
fds[0].events = POLLIN;
|
fds.events = POLLIN;
|
||||||
|
|
||||||
sigemptyset(&mask);
|
signal(SIGINT, signal_handler);
|
||||||
sigaddset(&mask, SIGINT);
|
|
||||||
fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
|
||||||
fds[1].events = POLLIN;
|
|
||||||
|
|
||||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
while (poll(&fds, 1, -1)) {
|
||||||
|
|
||||||
while (poll(fds, 2, -1)) {
|
|
||||||
struct input_event ev;
|
struct input_event ev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fds[1].revents)
|
if (signalled)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
@ -153,39 +151,28 @@ mainloop(struct libevdev *dev, struct measurements *m) {
|
||||||
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||||
fprintf(stderr, "Error: cannot keep up\n");
|
fprintf(stderr, "Error: cannot keep up\n");
|
||||||
return 1;
|
return 1;
|
||||||
} else if (rc != -EAGAIN && rc < 0) {
|
}
|
||||||
|
|
||||||
|
if (rc != -EAGAIN && rc < 0) {
|
||||||
fprintf(stderr, "Error: %s\n", strerror(-rc));
|
fprintf(stderr, "Error: %s\n", strerror(-rc));
|
||||||
return 1;
|
return 1;
|
||||||
} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
|
||||||
handle_event(m, &ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
|
||||||
|
handle_event(m, &ev);
|
||||||
} while (rc != -EAGAIN);
|
} while (rc != -EAGAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline double
|
||||||
print_summary(struct measurements *m)
|
mean_frequency(struct measurements *m)
|
||||||
{
|
{
|
||||||
int res;
|
int idx;
|
||||||
|
|
||||||
printf("Estimated sampling frequency: %dHz\n", (int)m->frequency);
|
idx = m->nfrequencies/2;
|
||||||
printf("To calculate resolution, measure physical distance covered\n"
|
return m->frequencies[idx];
|
||||||
"and look up the matching resolution in the table below\n");
|
|
||||||
|
|
||||||
m->distance = abs(m->distance);
|
|
||||||
|
|
||||||
/* If the mouse has more than 2500dpi, the manufacturer usually
|
|
||||||
shows off on their website anyway */
|
|
||||||
for (res = 400; res <= 2500; res += 200) {
|
|
||||||
double inch = m->distance/(double)res;
|
|
||||||
printf("%8dmm %8.2fin %8ddpi\n",
|
|
||||||
(int)(inch * 25.4), inch, res);
|
|
||||||
}
|
|
||||||
printf("If your resolution is not in the list, calculate it with:\n"
|
|
||||||
"\tresolution=%d/inches, or\n"
|
|
||||||
"\tresolution=%d * 25.4/mm\n", m->distance, m->distance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char*
|
static inline const char*
|
||||||
|
|
@ -206,20 +193,68 @@ bustype(int bustype)
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_summary(struct libevdev *dev, struct measurements *m)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
int max_freq, mean_freq;
|
||||||
|
|
||||||
|
if (m->nfrequencies == 0) {
|
||||||
|
fprintf(stderr, "Error: no matching events received.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_freq = (int)m->max_frequency;
|
||||||
|
mean_freq = (int)mean_frequency(m);
|
||||||
|
|
||||||
|
printf("Estimated sampling frequency: %dHz (mean %dHz)\n",
|
||||||
|
max_freq, mean_freq);
|
||||||
|
|
||||||
|
if (max_freq > mean_freq * 1.3)
|
||||||
|
printf("WARNING: Max frequency is more than 30%% higher "
|
||||||
|
"than mean frequency. Manual verification required!\n");
|
||||||
|
|
||||||
|
printf("To calculate resolution, measure physical distance covered\n"
|
||||||
|
"and look up the matching resolution in the table below\n");
|
||||||
|
|
||||||
|
m->distance = abs(m->distance);
|
||||||
|
|
||||||
|
/* If the mouse has more than 2500dpi, the manufacturer usually
|
||||||
|
shows off on their website anyway */
|
||||||
|
for (res = 400; res <= 2500; res += 200) {
|
||||||
|
double inch = m->distance/(double)res;
|
||||||
|
printf("%8dmm %8.2fin %8ddpi\n",
|
||||||
|
(int)(inch * 25.4), inch, res);
|
||||||
|
}
|
||||||
|
printf("If your resolution is not in the list, calculate it with:\n"
|
||||||
|
"\tresolution=%d/inches, or\n"
|
||||||
|
"\tresolution=%d * 25.4/mm\n", m->distance, m->distance);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf("Entry for hwdb match (replace XXX with the resolution in DPI):\n"
|
||||||
|
"mouse:%s:v%04xp%04x:name:%s:\n"
|
||||||
|
" MOUSE_DPI=XXX@%d\n",
|
||||||
|
bustype(libevdev_get_id_bustype(dev)),
|
||||||
|
libevdev_get_id_vendor(dev),
|
||||||
|
libevdev_get_id_product(dev),
|
||||||
|
libevdev_get_name(dev),
|
||||||
|
(int)m->max_frequency);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv) {
|
main (int argc, char **argv) {
|
||||||
int rc;
|
int rc;
|
||||||
int fd;
|
int fd;
|
||||||
const char *path;
|
const char *path;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
struct measurements measurements = {0, 0, 0};
|
struct measurements measurements = {0};
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
return usage();
|
return usage(basename(argv[0]));
|
||||||
|
|
||||||
path = argv[1];
|
path = argv[1];
|
||||||
if (path[0] == '-')
|
if (path[0] == '-')
|
||||||
return usage();
|
return usage(basename(argv[0]));
|
||||||
|
|
||||||
fd = open(path, O_RDONLY|O_NONBLOCK);
|
fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|
@ -249,17 +284,7 @@ main (int argc, char **argv) {
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
print_summary(&measurements);
|
print_summary(dev, &measurements);
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
printf("Entry for hwdb match (replace XXX with the resolution in DPI):\n"
|
|
||||||
"mouse:%s:v%04xp%04x:name:%s:\n"
|
|
||||||
" MOUSE_DPI=XXX@%d\n",
|
|
||||||
bustype(libevdev_get_id_bustype(dev)),
|
|
||||||
libevdev_get_id_vendor(dev),
|
|
||||||
libevdev_get_id_product(dev),
|
|
||||||
libevdev_get_name(dev),
|
|
||||||
(int)measurements.frequency);
|
|
||||||
|
|
||||||
libevdev_free(dev);
|
libevdev_free(dev);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,37 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
make
|
tag="$1"
|
||||||
rsync --delete -avz doc/html/ freedesktop.org:/srv/www.freedesktop.org/www/software/libevdev/doc/latest
|
case $tag in
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: $0 <tag>"
|
||||||
|
echo "Builds the libevdev documentation and rsyncs it to the freedesktop.org server."
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " tag ... the tag to build (default: master)"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
1*)
|
||||||
|
# Helper so we can run it with the numerical tag only, tags
|
||||||
|
# are all prefixed with libevdev
|
||||||
|
tag="libevdev-$tag"
|
||||||
|
;;
|
||||||
|
**)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
tag=${tag:-master}
|
||||||
|
|
||||||
|
dir=$(mktemp -d --tmpdir='' libevdev-doc.XXX)
|
||||||
|
git clone --depth 1 --branch "$tag" https://gitlab.freedesktop.org/libevdev/libevdev.git "$dir"
|
||||||
|
pushd $dir
|
||||||
|
builddir=_doc_build
|
||||||
|
rm -rf "$builddir"
|
||||||
|
meson setup "$builddir"
|
||||||
|
ninja -C "$builddir"
|
||||||
|
|
||||||
|
# Strip libevdev- prefix from the tag and replace master with latest, whichever applies
|
||||||
|
htmldir=${tag/#libevdev-/}
|
||||||
|
htmldir=${htmldir/master/latest}
|
||||||
|
rsync --delete -avz "$builddir/html/" freedesktop.org:/srv/www.freedesktop.org/www/software/libevdev/doc/${htmldir}
|
||||||
|
popd
|
||||||
|
|
|
||||||
31
tools/sync-with-kernel-headers.sh
Executable file
31
tools/sync-with-kernel-headers.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Syncs the repository with the input.h and input-event-codes.h headers from
|
||||||
|
# a checked out source directory.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# sync-with-kernel-headers.sh path/to/kernel v4.12
|
||||||
|
|
||||||
|
KERNEL_TREE="$1"
|
||||||
|
GIT_DIR="$KERNEL_TREE/.git"
|
||||||
|
TAG="$2"
|
||||||
|
|
||||||
|
export GIT_DIR
|
||||||
|
|
||||||
|
if [ -z "$TAG" ] || ! [ -d "$GIT_DIR" ]; then
|
||||||
|
echo "Usage: `basename $0` path/to/kernel tag"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! [ -d .git ]; then
|
||||||
|
echo "Run me from the top-level git tree"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
file="linux/input.h"
|
||||||
|
git cat-file -p "$TAG:include/uapi/$file" > "include/linux/linux/$(basename $file)"
|
||||||
|
|
||||||
|
file="linux/input-event-codes.h"
|
||||||
|
git cat-file -p "$TAG:include/uapi/$file" > "include/linux/linux/$(basename $file)"
|
||||||
|
git cat-file -p "$TAG:include/uapi/$file" > "include/linux/freebsd/$(basename $file)"
|
||||||
|
|
||||||
44
tools/touchpad-edge-detector.1
Normal file
44
tools/touchpad-edge-detector.1
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
.TH TOUCHPAD-EDGE-DETECTOR "1"
|
||||||
|
.SH NAME
|
||||||
|
touchpad-edge-detector \- print the axis ranges for a touchpad device
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B touchpad-edge-detector [--help] \fIWxH /dev/input/eventX\fR
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B touchpad-edge-detector
|
||||||
|
tool reads touchpad events from the kernel and records the minimum and
|
||||||
|
maximum coordinates based on user input. This is an interactive tool, the
|
||||||
|
user must move a finger around the touchpad, attempting to trigger an
|
||||||
|
event at all edges of the touchpad.
|
||||||
|
.PP
|
||||||
|
To terminate the event collection and print a summary, press Ctrl+C. It is
|
||||||
|
recommended that the tool is run several times to guarantee a reliable
|
||||||
|
result.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP 8
|
||||||
|
.I WxH
|
||||||
|
The width and height of the touchpad in mm. For a touchpad 100mm wide and
|
||||||
|
75mm high, the argument is thus \fI100x75\fR. This is a required argument.
|
||||||
|
.TP 8
|
||||||
|
.I /dev/input/eventX
|
||||||
|
The event node of the touchpad to read events from. A list of possible event
|
||||||
|
nodes can be obtained with either one of the following commands: \fBlibinput
|
||||||
|
record\fR, \fBevemu-record\fR, or \fBevtest\fR. Alternatively the event node
|
||||||
|
for a device is listed in the \fBHandlers=\fR line \fI/proc/bus/input/devices\fR.
|
||||||
|
This is a required argument.
|
||||||
|
.TP 8
|
||||||
|
.B --help
|
||||||
|
Print a short help description
|
||||||
|
.SH NOTES
|
||||||
|
.PP
|
||||||
|
On completion, this tool prints a summary of the collected events and a
|
||||||
|
suggested udev rule. Due to rounding errors it is rare to get an exact match
|
||||||
|
for the touchpad's dimensions, but any discrepancy of more than 5mm should
|
||||||
|
be corrected with the suggested udev rule.
|
||||||
|
.PP
|
||||||
|
The udev rule should be simplified and submitted as a pull request to the
|
||||||
|
system repository at \fIhttps://github.com/systemd/systemd\fR. For further
|
||||||
|
guidance, see the file \fI/usr/lib/udev/hwdb.d/60-evdev.hwdb\fR.
|
||||||
|
.SH SEE ALSO
|
||||||
|
udev(7)
|
||||||
|
|
@ -1,52 +1,37 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
/*
|
/*
|
||||||
* Copyright © 2014 Red Hat, Inc.
|
* Copyright © 2014 Red Hat, Inc.
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, distribute, and sell this software
|
|
||||||
* and its documentation for any purpose is hereby granted without
|
|
||||||
* fee, provided that the above copyright notice appear in all copies
|
|
||||||
* and that both that copyright notice and this permission notice
|
|
||||||
* appear in supporting documentation, and that the name of Red Hat
|
|
||||||
* not be used in advertising or publicity pertaining to distribution
|
|
||||||
* of the software without specific, written prior permission. Red
|
|
||||||
* Hat makes no representations about the suitability of this software
|
|
||||||
* for any purpose. It is provided "as is" without express or implied
|
|
||||||
* warranty.
|
|
||||||
*
|
|
||||||
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
||||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
||||||
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
||||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
||||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libevdev/libevdev.h>
|
|
||||||
#include <sys/signalfd.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "libevdev/libevdev.h"
|
||||||
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
static int signalled = 0;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
usage(void) {
|
usage(const char *progname) {
|
||||||
printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
|
printf("Usage: %s 12x34 /dev/input/eventX\n", progname);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("This tool reads the touchpad events from the kernel and calculates\n "
|
printf("This tool reads the touchpad events from the kernel and calculates\n "
|
||||||
"the minimum and maximum for the x and y coordinates, respectively.\n");
|
"the minimum and maximum for the x and y coordinates, respectively.\n"
|
||||||
|
"The first argument is the physical size of the touchpad in mm (WIDTHxHEIGHT).\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,6 +39,10 @@ struct dimensions {
|
||||||
int top, bottom, left, right;
|
int top, bottom, left, right;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct size {
|
||||||
|
int w, h;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
print_current_values(const struct dimensions *d)
|
print_current_values(const struct dimensions *d)
|
||||||
{
|
{
|
||||||
|
|
@ -76,9 +65,10 @@ print_current_values(const struct dimensions *d)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handle_event(struct dimensions *d, const struct input_event *ev) {
|
handle_event(struct dimensions *d, const struct input_event *ev) {
|
||||||
if (ev->type == EV_SYN) {
|
if (ev->type == EV_SYN)
|
||||||
return print_current_values(d);
|
return print_current_values(d);
|
||||||
} else if (ev->type != EV_ABS)
|
|
||||||
|
if (ev->type != EV_ABS)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch(ev->code) {
|
switch(ev->code) {
|
||||||
|
|
@ -97,26 +87,26 @@ handle_event(struct dimensions *d, const struct input_event *ev) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler(__attribute__((__unused__)) int signal)
|
||||||
|
{
|
||||||
|
signalled++;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mainloop(struct libevdev *dev, struct dimensions *dim) {
|
mainloop(struct libevdev *dev, struct dimensions *dim) {
|
||||||
struct pollfd fds[2];
|
struct pollfd fds;
|
||||||
sigset_t mask;
|
|
||||||
|
|
||||||
fds[0].fd = libevdev_get_fd(dev);
|
fds.fd = libevdev_get_fd(dev);
|
||||||
fds[0].events = POLLIN;
|
fds.events = POLLIN;
|
||||||
|
|
||||||
sigemptyset(&mask);
|
signal(SIGINT, signal_handler);
|
||||||
sigaddset(&mask, SIGINT);
|
|
||||||
fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
|
||||||
fds[1].events = POLLIN;
|
|
||||||
|
|
||||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
while (poll(&fds, 1, -1)) {
|
||||||
|
|
||||||
while (poll(fds, 2, -1)) {
|
|
||||||
struct input_event ev;
|
struct input_event ev;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fds[1].revents)
|
if (signalled)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
@ -124,12 +114,16 @@ mainloop(struct libevdev *dev, struct dimensions *dim) {
|
||||||
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||||
fprintf(stderr, "Error: cannot keep up\n");
|
fprintf(stderr, "Error: cannot keep up\n");
|
||||||
return 1;
|
return 1;
|
||||||
} else if (rc != -EAGAIN && rc < 0) {
|
}
|
||||||
|
|
||||||
|
if (rc != -EAGAIN && rc < 0) {
|
||||||
fprintf(stderr, "Error: %s\n", strerror(-rc));
|
fprintf(stderr, "Error: %s\n", strerror(-rc));
|
||||||
return 1;
|
return 1;
|
||||||
} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
|
||||||
handle_event(dim, &ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == LIBEVDEV_READ_STATUS_SUCCESS)
|
||||||
|
handle_event(dim, &ev);
|
||||||
} while (rc != -EAGAIN);
|
} while (rc != -EAGAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,31 +157,35 @@ dmi_matchstr(struct libevdev *dev, char *match, size_t sz)
|
||||||
|
|
||||||
modalias[strlen(modalias) - 1] = '\0'; /* drop \n */
|
modalias[strlen(modalias) - 1] = '\0'; /* drop \n */
|
||||||
snprintf(match, sz, "name:%s:%s", libevdev_get_name(dev), modalias);
|
snprintf(match, sz, "name:%s:%s", libevdev_get_name(dev), modalias);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_udev_override_rule(struct libevdev *dev, const struct dimensions *dim) {
|
print_udev_override_rule(struct libevdev *dev,
|
||||||
|
const struct dimensions *dim,
|
||||||
|
const struct size *size) {
|
||||||
const struct input_absinfo *x, *y;
|
const struct input_absinfo *x, *y;
|
||||||
char match[PATH_MAX];
|
char match[PATH_MAX];
|
||||||
int w, h;
|
int w, h;
|
||||||
|
int xres, yres;
|
||||||
|
|
||||||
x = libevdev_get_abs_info(dev, ABS_X);
|
x = libevdev_get_abs_info(dev, ABS_X);
|
||||||
y = libevdev_get_abs_info(dev, ABS_Y);
|
y = libevdev_get_abs_info(dev, ABS_Y);
|
||||||
w = x->maximum - x->minimum;
|
w = dim->right - dim->left;
|
||||||
h = y->maximum - y->minimum;
|
h = dim->bottom - dim->top;
|
||||||
|
xres = round((double)w/size->w);
|
||||||
|
yres = round((double)h/size->h);
|
||||||
|
|
||||||
if (x->resolution && y->resolution) {
|
if (x->resolution && y->resolution) {
|
||||||
|
int width = x->maximum - x->minimum,
|
||||||
|
height = y->maximum - y->minimum;
|
||||||
printf("Touchpad size as listed by the kernel: %dx%dmm\n",
|
printf("Touchpad size as listed by the kernel: %dx%dmm\n",
|
||||||
w/x->resolution, h/y->resolution);
|
width/x->resolution, height/y->resolution);
|
||||||
} else {
|
} else {
|
||||||
printf("Touchpad has no resolution, size unknown\n");
|
printf("Touchpad has no resolution, size unknown\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Calculate resolution as:\n");
|
printf("User-specified touchpad size: %dx%dmm\n", size->w, size->h);
|
||||||
printf(" x axis: %d/<width in mm>\n", w);
|
printf("Calculated ranges: %d/%d\n", w, h);
|
||||||
printf(" y axis: %d/<height in mm>\n", h);
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Suggested udev rule:\n");
|
printf("Suggested udev rule:\n");
|
||||||
|
|
||||||
|
|
@ -203,16 +201,16 @@ print_udev_override_rule(struct libevdev *dev, const struct dimensions *dim) {
|
||||||
|
|
||||||
printf("# <Laptop model description goes here>\n"
|
printf("# <Laptop model description goes here>\n"
|
||||||
"evdev:%s*\n"
|
"evdev:%s*\n"
|
||||||
" EVDEV_ABS_00=%d:%d:<x resolution>\n"
|
" EVDEV_ABS_00=%d:%d:%d\n"
|
||||||
" EVDEV_ABS_01=%d:%d:<y resolution>\n",
|
" EVDEV_ABS_01=%d:%d:%d\n",
|
||||||
match,
|
match,
|
||||||
dim->left, dim->right,
|
dim->left, dim->right, xres,
|
||||||
dim->top, dim->bottom);
|
dim->top, dim->bottom, yres);
|
||||||
if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_X))
|
if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_X))
|
||||||
printf(" EVDEV_ABS_35=%d:%d:<x resolution>\n"
|
printf(" EVDEV_ABS_35=%d:%d:%d\n"
|
||||||
" EVDEV_ABS_36=%d:%d:<y resolution>\n",
|
" EVDEV_ABS_36=%d:%d:%d\n",
|
||||||
dim->left, dim->right,
|
dim->left, dim->right, xres,
|
||||||
dim->top, dim->bottom);
|
dim->top, dim->bottom, yres);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
|
|
@ -221,13 +219,26 @@ int main (int argc, char **argv) {
|
||||||
const char *path;
|
const char *path;
|
||||||
struct libevdev *dev;
|
struct libevdev *dev;
|
||||||
struct dimensions dim;
|
struct dimensions dim;
|
||||||
|
struct size size;
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 3)
|
||||||
return usage();
|
return usage(basename(argv[0]));
|
||||||
|
|
||||||
path = argv[1];
|
if (sscanf(argv[1], "%dx%d", &size.w, &size.h) != 2 ||
|
||||||
|
size.w <= 0 || size.h <= 0)
|
||||||
|
return usage(basename(argv[0]));
|
||||||
|
|
||||||
|
if (size.w < 30 || size.h < 30) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%dx%dmm is too small for a touchpad.\n"
|
||||||
|
"Please specify the touchpad size in mm.\n",
|
||||||
|
size.w, size.h);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = argv[2];
|
||||||
if (path[0] == '-')
|
if (path[0] == '-')
|
||||||
return usage();
|
return usage(basename(argv[0]));
|
||||||
|
|
||||||
fd = open(path, O_RDONLY|O_NONBLOCK);
|
fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|
@ -273,7 +284,7 @@ int main (int argc, char **argv) {
|
||||||
rc = mainloop(dev, &dim);
|
rc = mainloop(dev, &dim);
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
|
|
||||||
print_udev_override_rule(dev, &dim);
|
print_udev_override_rule(dev, &dim, &size);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
libevdev_free(dev);
|
libevdev_free(dev);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue