mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-25 21:00:07 +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?
|
||||
# Edit Compile Debug Document Distribute
|
||||
*~
|
||||
*.[0-9]
|
||||
*.[0-9]x
|
||||
*.bak
|
||||
*.bin
|
||||
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 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.
|
||||
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 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.
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
The following license is from a Linux kernel header file and there is no GPL
|
||||
code this package links to.
|
||||
|
|
|
|||
|
|
@ -8,4 +8,4 @@ SUBDIRS = doc libevdev tools test
|
|||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
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
|
||||
interface to the callers, thus avoiding erroneous ioctls, etc.
|
||||
|
||||
git://git.freedesktop.org/git/libevdev
|
||||
http://cgit.freedesktop.org/libevdev/
|
||||
|
||||
The eventual goal is that libevdev wraps all ioctls available to evdev
|
||||
devices, thus making direct access unnecessary.
|
||||
https://gitlab.freedesktop.org/libevdev/libevdev.git
|
||||
|
||||
Go here for the API documentation:
|
||||
http://www.freedesktop.org/software/libevdev/doc/latest/
|
||||
|
||||
File bugs in the freedesktop.org bugzilla:
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev
|
||||
File bugs in the freedesktop.org GitLab instance:
|
||||
https://gitlab.freedesktop.org/libevdev/libevdev/issues/
|
||||
|
||||
Patches, questions and general comments should be submitted to the input-tools@lists.freedesktop.org
|
||||
mailing list:
|
||||
Patches should be submitted as merge requests in the GitLab instance:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -9,4 +9,8 @@ cd "$srcdir"
|
|||
autoreconf -fvi || exit $?
|
||||
|
||||
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.
|
||||
#
|
||||
# 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])
|
||||
|
||||
# change meson version too
|
||||
AC_INIT([libevdev],
|
||||
[1.5.0],
|
||||
[https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev],
|
||||
[1.13.6],
|
||||
[https://gitlab.freedesktop.org/libevdev/libevdev/issues/],
|
||||
[libevdev],
|
||||
[http://freedesktop.org/wiki/Software/libevdev/])
|
||||
|
||||
|
|
@ -32,17 +18,11 @@ AC_CONFIG_MACRO_DIR([m4])
|
|||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
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
|
||||
# modified.
|
||||
# The string is of the form C:R:A.
|
||||
# - 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
|
||||
# DO NOT MODIFY THIS
|
||||
# Use symbol versioning instead.
|
||||
LIBEVDEV_LT_VERSION=5:0:3
|
||||
AC_SUBST(LIBEVDEV_LT_VERSION)
|
||||
|
||||
|
||||
|
|
@ -66,14 +46,22 @@ if test "x$lt_cv_prog_gnu_ld" = "xyes"; then
|
|||
fi
|
||||
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_CHECK_MODULES(CHECK, [check >= 0.9.9], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
|
||||
if test "x$HAVE_CHECK" = "xyes"; then
|
||||
AC_PATH_PROG(VALGRIND, [valgrind])
|
||||
else
|
||||
if test "x$HAVE_CHECK" != "xyes"; then
|
||||
AC_MSG_WARN([check not found - skipping building unit tests])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"])
|
||||
AM_CONDITIONAL(ENABLE_RUNTIME_TESTS, [test "x$HAVE_CHECK" = "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"],
|
||||
[
|
||||
GCOV_CFLAGS="-fprofile-arcs -ftest-coverage"
|
||||
GCOV_LDFLAGS="-fprofile-arcs -ftest-coverage"
|
||||
GCOV_LDFLAGS="-lgcov"
|
||||
enable_gcov=yes
|
||||
],
|
||||
)
|
||||
|
|
@ -124,8 +112,27 @@ AC_SUBST([GCOV_CFLAGS])
|
|||
AC_SUBST([GCOV_LDFLAGS])
|
||||
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])
|
||||
AC_PATH_PROG(CAT, [cat])
|
||||
|
||||
# nm to check for leaking symbols in the static library
|
||||
AC_PATH_PROG(NM, [nm])
|
||||
|
|
@ -162,5 +169,6 @@ AC_MSG_RESULT([
|
|||
Build documentation ${have_doxygen}
|
||||
Enable unit-tests ${HAVE_CHECK}
|
||||
Enable profiling ${enable_gcov}
|
||||
Enable coverity support ${enable_coverity}
|
||||
Static library symbol check ${static_symbol_leaks_test}
|
||||
])
|
||||
|
|
|
|||
|
|
@ -8,14 +8,27 @@ header_files = \
|
|||
$(top_srcdir)/libevdev/libevdev.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) $<
|
||||
|
||||
clean-local:
|
||||
$(AM_V_at)rm -rf html
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
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
|
||||
EXAMPLE_PATH = @top_srcdir@/include
|
||||
GENERATE_HTML = YES
|
||||
HTML_EXTRA_STYLESHEET = @srcdir@/libevdev.css
|
||||
HTML_TIMESTAMP = YES
|
||||
GENERATE_LATEX = NO
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
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
|
||||
*
|
||||
|
|
@ -26,6 +27,7 @@
|
|||
#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */
|
||||
#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */
|
||||
#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */
|
||||
#define INPUT_PROP_PRESSUREPAD 0x07 /* pressure triggers clicks */
|
||||
|
||||
#define INPUT_PROP_MAX 0x1f
|
||||
#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1)
|
||||
|
|
@ -277,7 +279,8 @@
|
|||
#define KEY_PAUSECD 201
|
||||
#define KEY_PROG3 202
|
||||
#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_CLOSE 206 /* AC Close */
|
||||
#define KEY_PLAY 207
|
||||
|
|
@ -406,6 +409,7 @@
|
|||
#define BTN_TOOL_MOUSE 0x146
|
||||
#define BTN_TOOL_LENS 0x147
|
||||
#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
|
||||
#define BTN_STYLUS3 0x149
|
||||
#define BTN_TOUCH 0x14a
|
||||
#define BTN_STYLUS 0x14b
|
||||
#define BTN_STYLUS2 0x14c
|
||||
|
|
@ -437,10 +441,12 @@
|
|||
#define KEY_TITLE 0x171
|
||||
#define KEY_SUBTITLE 0x172
|
||||
#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_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_TV 0x179 /* Media Select TV */
|
||||
#define KEY_TV2 0x17a /* Media Select Cable */
|
||||
|
|
@ -511,6 +517,10 @@
|
|||
#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */
|
||||
#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */
|
||||
#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_EOS 0x1c1
|
||||
|
|
@ -538,6 +548,7 @@
|
|||
#define KEY_FN_F 0x1e2
|
||||
#define KEY_FN_S 0x1e3
|
||||
#define KEY_FN_B 0x1e4
|
||||
#define KEY_FN_RIGHT_SHIFT 0x1e5
|
||||
|
||||
#define KEY_BRL_DOT1 0x1f1
|
||||
#define KEY_BRL_DOT2 0x1f2
|
||||
|
|
@ -591,7 +602,14 @@
|
|||
#define BTN_DPAD_LEFT 0x222
|
||||
#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_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_TASKMANAGER 0x241 /* AL Task/Project Manager */
|
||||
|
|
@ -600,10 +618,31 @@
|
|||
#define KEY_APPSELECT 0x244 /* AL Select Task/Application */
|
||||
#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */
|
||||
#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_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_NEXT 0x261
|
||||
#define KEY_KBDINPUTASSIST_PREVGROUP 0x262
|
||||
|
|
@ -611,6 +650,142 @@
|
|||
#define KEY_KBDINPUTASSIST_ACCEPT 0x264
|
||||
#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_HAPPY1 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY2 0x2c1
|
||||
|
|
@ -672,6 +847,16 @@
|
|||
#define REL_DIAL 0x07
|
||||
#define REL_WHEEL 0x08
|
||||
#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_CNT (REL_MAX+1)
|
||||
|
||||
|
|
@ -705,9 +890,19 @@
|
|||
#define ABS_TOOL_WIDTH 0x1c
|
||||
|
||||
#define ABS_VOLUME 0x20
|
||||
#define ABS_PROFILE 0x21
|
||||
|
||||
#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_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||
#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_Y 0x3d /* Center Y tool position */
|
||||
|
||||
|
||||
#define ABS_MAX 0x3f
|
||||
#define ABS_CNT (ABS_MAX+1)
|
||||
|
||||
|
|
@ -748,7 +944,10 @@
|
|||
#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */
|
||||
#define SW_LINEIN_INSERT 0x0d /* set = inserted */
|
||||
#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)
|
||||
|
||||
/*
|
||||
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 @@
|
|||
/*
|
||||
* 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 _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 */
|
||||
#ifdef __linux__
|
||||
#include "linux/input.h"
|
||||
#elif __FreeBSD__
|
||||
#include "freebsd/input.h"
|
||||
#endif
|
||||
|
|
|
|||
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 @@
|
|||
/*
|
||||
* 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_ */
|
||||
#ifdef __linux__
|
||||
#include "linux/uinput.h"
|
||||
#elif __FreeBSD__
|
||||
#include "freebsd/uinput.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
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.h \
|
||||
|
|
@ -11,11 +12,14 @@ libevdev_la_SOURCES = \
|
|||
libevdev-uinput-int.h \
|
||||
libevdev.c \
|
||||
libevdev-names.c \
|
||||
../include/linux/input-event-codes.h \
|
||||
../include/linux/input.h
|
||||
../include/linux/uinput.h
|
||||
../include/linux/input.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 = \
|
||||
$(AM_LDFLAGS) \
|
||||
-version-info $(LIBEVDEV_LT_VERSION) \
|
||||
-Wl,--version-script="$(srcdir)/libevdev.sym" \
|
||||
$(GNU_LD_FLAGS)
|
||||
|
|
@ -26,10 +30,13 @@ libevdevincludedir = $(includedir)/libevdev-1.0/libevdev
|
|||
libevdevinclude_HEADERS = libevdev.h libevdev-uinput.h
|
||||
|
||||
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
|
||||
BUILT_SOURCES = event-names.h
|
||||
|
||||
if GCOV_ENABLED
|
||||
CLEANFILES += *.gcno
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,29 +1,12 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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
|
||||
#define LIBEVDEV_INT_H
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -55,11 +38,6 @@ enum SyncState {
|
|||
SYNC_IN_PROGRESS,
|
||||
};
|
||||
|
||||
struct mt_sync_state {
|
||||
int code;
|
||||
int val[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal only: log data used to send messages to the respective log
|
||||
* handler. We re-use the same struct for a global and inside
|
||||
|
|
@ -112,15 +90,6 @@ struct libevdev {
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
@ -143,6 +112,16 @@ _libevdev_log_msg(const struct libevdev *dev,
|
|||
extern enum libevdev_log_priority
|
||||
_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
|
||||
* is full.
|
||||
|
|
@ -156,6 +135,18 @@ queue_push(struct libevdev *dev)
|
|||
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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,34 +1,18 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "libevdev-int.h"
|
||||
#include "libevdev-util.h"
|
||||
#include "libevdev.h"
|
||||
|
||||
#include "event-names.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* 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 {
|
||||
|
|
|
|||
|
|
@ -1,44 +1,25 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "config.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 <time.h>
|
||||
#include <linux/uinput.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "libevdev-int.h"
|
||||
#include "libevdev-uinput.h"
|
||||
#include "libevdev-uinput-int.h"
|
||||
#include "libevdev-uinput.h"
|
||||
#include "libevdev-util.h"
|
||||
|
||||
#define SYS_INPUT_DIR "/sys/devices/virtual/input/"
|
||||
#include "libevdev.h"
|
||||
|
||||
#ifndef UINPUT_IOCTL_BASE
|
||||
#define UINPUT_IOCTL_BASE 'U'
|
||||
|
|
@ -182,6 +163,35 @@ libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev)
|
|||
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) {
|
||||
return strncmp("event", dent->d_name, 5) == 0;
|
||||
}
|
||||
|
|
@ -217,6 +227,7 @@ static int is_input_device(const struct dirent *dent) {
|
|||
static int
|
||||
fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
||||
{
|
||||
#define SYS_INPUT_DIR "/sys/devices/virtual/input/"
|
||||
struct dirent **namelist;
|
||||
int ndev, i;
|
||||
int rc;
|
||||
|
|
@ -270,18 +281,19 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
|
|||
/* FIXME: could descend into bit comparison here */
|
||||
log_info(NULL, "multiple identical devices found. syspath is unreliable\n");
|
||||
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);
|
||||
|
||||
return uinput_dev->devnode ? 0 : -1;
|
||||
#undef SYS_INPUT_DIR
|
||||
}
|
||||
#endif /* __FreeBSD__*/
|
||||
|
||||
static int
|
||||
uinput_create_write(const struct libevdev *dev, int fd,
|
||||
struct libevdev_uinput *new_device)
|
||||
uinput_create_write(const struct libevdev *dev, int fd)
|
||||
{
|
||||
int rc;
|
||||
struct uinput_user_dev uidev;
|
||||
|
|
@ -313,9 +326,9 @@ uinput_create_write(const struct libevdev *dev, int fd,
|
|||
goto error;
|
||||
|
||||
rc = write(fd, &uidev, sizeof(uidev));
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
else if ((size_t)rc < sizeof(uidev)) {
|
||||
} else if ((size_t)rc < sizeof(uidev)) {
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
|
@ -381,7 +394,7 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li
|
|||
uinput_version >= 5)
|
||||
rc = uinput_create_DEV_SETUP(dev, fd, new_device);
|
||||
else
|
||||
rc = uinput_create_write(dev, fd, new_device);
|
||||
rc = uinput_create_write(dev, fd);
|
||||
|
||||
if (rc != 0)
|
||||
goto error;
|
||||
|
|
@ -455,7 +468,13 @@ libevdev_uinput_write_event(const struct libevdev_uinput *uinput_dev,
|
|||
unsigned int code,
|
||||
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 rc, max;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,25 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* 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.
|
||||
* 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 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.
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBEVDEV_UINPUT_H
|
||||
|
|
@ -40,21 +42,20 @@ struct libevdev_uinput;
|
|||
*
|
||||
* @code
|
||||
* int err;
|
||||
* int fd, new_fd, uifd;
|
||||
* int fd, uifd;
|
||||
* struct libevdev *dev;
|
||||
* struct libevdev_uinput *uidev;
|
||||
* struct input_event ev[2];
|
||||
*
|
||||
* fd = open("/dev/input/event0", O_RDONLY);
|
||||
* if (fd < 0)
|
||||
* return err;
|
||||
* return -errno;
|
||||
*
|
||||
* err = libevdev_new_from_fd(fd, &dev);
|
||||
* if (err != 0)
|
||||
* return err;
|
||||
*
|
||||
* uifd = open("/dev/uinput", O_RDWR);
|
||||
* if (uidev < 0)
|
||||
* if (uifd < 0)
|
||||
* return -errno;
|
||||
*
|
||||
* 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);
|
||||
* if (err != 0)
|
||||
* 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)
|
||||
* return err;
|
||||
*
|
||||
|
|
@ -107,7 +108,7 @@ struct libevdev_uinput;
|
|||
*/
|
||||
|
||||
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
|
||||
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 */
|
||||
|
|
@ -138,6 +139,9 @@ enum libevdev_uinput_open_mode {
|
|||
* REP_PERIOD will default to the kernel defaults, not to the ones set in the
|
||||
* 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 uinput_fd @ref LIBEVDEV_UINPUT_OPEN_MANAGED or a file descriptor to @c /dev/uinput,
|
||||
* @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
|
||||
*
|
||||
* 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 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.
|
||||
* 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
|
||||
* creating devices that have the same name.
|
||||
* To avoid false positives, wait at least 1.5s between creating devices that
|
||||
* 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.
|
||||
* @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
|
||||
* 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.
|
||||
* @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.
|
||||
*
|
||||
* 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_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <config.h>
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -34,6 +17,7 @@
|
|||
|
||||
#undef min
|
||||
#undef max
|
||||
#ifdef __GNUC__
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
|
|
@ -44,6 +28,10 @@
|
|||
__typeof__ (b) _b = (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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,38 +1,23 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <stdarg.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-util.h"
|
||||
#include "libevdev.h"
|
||||
|
||||
#include "event-names.h"
|
||||
|
||||
#define MAXEVENTS 64
|
||||
|
|
@ -43,7 +28,26 @@ enum event_filter_status {
|
|||
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*
|
||||
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)
|
||||
return;
|
||||
} else if (!log_data.global_handler || priority > log_data.priority)
|
||||
} else if (!log_data.global_handler || priority > log_data.priority) {
|
||||
return;
|
||||
else if (unlikely(log_data.device_handler))
|
||||
} else if (unlikely(log_data.device_handler)) {
|
||||
abort(); /* Seppuku, see above */
|
||||
}
|
||||
|
||||
va_start(args, format);
|
||||
if (dev && dev->log.device_handler)
|
||||
|
|
@ -199,9 +204,6 @@ libevdev_reset(struct libevdev *dev)
|
|||
free(dev->phys);
|
||||
free(dev->uniq);
|
||||
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));
|
||||
dev->fd = -1;
|
||||
dev->initialized = false;
|
||||
|
|
@ -299,8 +301,7 @@ _libevdev_log_priority(const struct libevdev *dev)
|
|||
{
|
||||
if (dev && dev->log.device_handler)
|
||||
return dev->log.priority;
|
||||
else
|
||||
return libevdev_get_log_priority();
|
||||
return libevdev_get_log_priority();
|
||||
}
|
||||
|
||||
LIBEVDEV_EXPORT int
|
||||
|
|
@ -311,9 +312,65 @@ libevdev_change_fd(struct libevdev *dev, int fd)
|
|||
return -1;
|
||||
}
|
||||
dev->fd = fd;
|
||||
dev->grabbed = LIBEVDEV_UNGRAB;
|
||||
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_set_fd(struct libevdev* dev, int fd)
|
||||
{
|
||||
|
|
@ -324,8 +381,11 @@ libevdev_set_fd(struct libevdev* dev, int fd)
|
|||
if (dev->initialized) {
|
||||
log_bug(dev, "device already initialized.\n");
|
||||
return -EBADF;
|
||||
} else if (fd < 0)
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
libevdev_reset(dev);
|
||||
|
||||
|
|
@ -460,41 +520,13 @@ libevdev_set_fd(struct libevdev* dev, int fd)
|
|||
|
||||
dev->fd = fd;
|
||||
|
||||
/* devices with ABS_MT_SLOT - 1 aren't MT devices,
|
||||
see the documentation for multitouch-related
|
||||
functions for more details */
|
||||
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;
|
||||
rc = init_slots(dev);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
abs_info = libevdev_get_abs_info(dev, ABS_MT_SLOT);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
if (dev->num_slots != -1) {
|
||||
struct slot_change_state unused[dev->num_slots];
|
||||
sync_mt_state(dev, unused);
|
||||
}
|
||||
|
||||
rc = init_event_queue(dev);
|
||||
|
|
@ -521,15 +553,6 @@ libevdev_get_fd(const struct libevdev* dev)
|
|||
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
|
||||
sync_key_state(struct libevdev *dev)
|
||||
{
|
||||
|
|
@ -545,10 +568,8 @@ sync_key_state(struct libevdev *dev)
|
|||
int old, new;
|
||||
old = bit_is_set(dev->key_values, i);
|
||||
new = bit_is_set(keystate, i);
|
||||
if (old ^ new) {
|
||||
struct input_event *ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_KEY, i, new ? 1 : 0);
|
||||
}
|
||||
if (old ^ new)
|
||||
queue_push_event(dev, EV_KEY, i, new ? 1 : 0);
|
||||
}
|
||||
|
||||
memcpy(dev->key_values, keystate, rc);
|
||||
|
|
@ -573,10 +594,8 @@ sync_sw_state(struct libevdev *dev)
|
|||
int old, new;
|
||||
old = bit_is_set(dev->sw_values, i);
|
||||
new = bit_is_set(swstate, i);
|
||||
if (old ^ new) {
|
||||
struct input_event *ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_SW, i, new ? 1 : 0);
|
||||
}
|
||||
if (old ^ new)
|
||||
queue_push_event(dev, EV_SW, i, new ? 1 : 0);
|
||||
}
|
||||
|
||||
memcpy(dev->sw_values, swstate, rc);
|
||||
|
|
@ -602,8 +621,7 @@ sync_led_state(struct libevdev *dev)
|
|||
old = bit_is_set(dev->led_values, i);
|
||||
new = bit_is_set(ledstate, i);
|
||||
if (old ^ new) {
|
||||
struct input_event *ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_LED, i, new ? 1 : 0);
|
||||
queue_push_event(dev, EV_LED, i, new ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -633,9 +651,7 @@ sync_abs_state(struct libevdev *dev)
|
|||
goto out;
|
||||
|
||||
if (dev->abs_info[i].value != abs_info.value) {
|
||||
struct input_event *ev = queue_push(dev);
|
||||
|
||||
init_event(dev, ev, EV_ABS, i, abs_info.value);
|
||||
queue_push_event(dev, EV_ABS, i, abs_info.value);
|
||||
dev->abs_info[i].value = abs_info.value;
|
||||
}
|
||||
}
|
||||
|
|
@ -646,105 +662,176 @@ out:
|
|||
}
|
||||
|
||||
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;
|
||||
struct input_absinfo abs_info;
|
||||
int rc;
|
||||
int axis, slot;
|
||||
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;
|
||||
#define MAX_SLOTS 256
|
||||
int rc = 0;
|
||||
struct slot_change_state changes[MAX_SLOTS] = {0};
|
||||
unsigned int nslots = min(MAX_SLOTS, dev->num_slots);
|
||||
|
||||
memset(dev->mt_sync.slot_update, 0, dev->mt_sync.slot_update_sz);
|
||||
memset(dev->mt_sync.tracking_id_changes, 0,
|
||||
dev->mt_sync.tracking_id_changes_sz);
|
||||
for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||||
/* EVIOCGMTSLOTS required format */
|
||||
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)
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
if (!libevdev_has_event_code(dev, EV_ABS, axis))
|
||||
continue;
|
||||
mt_state.code = axis;
|
||||
rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(mt_state)), &mt_state);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
mt_state->code = axis;
|
||||
rc = ioctl(dev->fd, EVIOCGMTSLOTS(dev->mt_sync.mt_state_sz), mt_state);
|
||||
if (rc < 0) {
|
||||
/* 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 (unsigned int slot = 0; slot < nslots; slot++) {
|
||||
int val_before = *slot_value(dev, slot, axis),
|
||||
val_after = mt_state.val[slot];
|
||||
|
||||
for (slot = 0; slot < dev->num_slots; slot++) {
|
||||
|
||||
if (*slot_value(dev, slot, axis) == mt_state->val[slot])
|
||||
continue;
|
||||
|
||||
if (axis == ABS_MT_TRACKING_ID &&
|
||||
*slot_value(dev, slot, axis) != -1 &&
|
||||
mt_state->val[slot] != -1) {
|
||||
set_bit(tracking_id_changes, slot);
|
||||
need_tracking_id_changes = 1;
|
||||
if (axis == ABS_MT_TRACKING_ID) {
|
||||
if (val_before == -1 && val_after != -1) {
|
||||
changes[slot].state = TOUCH_STARTED;
|
||||
} else if (val_before != -1 && val_after == -1) {
|
||||
changes[slot].state = TOUCH_STOPPED;
|
||||
} else if (val_before != -1 && val_after != -1 &&
|
||||
val_before == val_after) {
|
||||
changes[slot].state = TOUCH_ONGOING;
|
||||
} else if (val_before != -1 && val_after != -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 (!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))
|
||||
if (val_before == val_after)
|
||||
continue;
|
||||
|
||||
ev = queue_push(dev);
|
||||
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);
|
||||
*slot_value(dev, slot, axis) = val_after;
|
||||
|
||||
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 (!bit_is_set(slot_update, AXISBIT(slot, ABS_MT_SLOT)))
|
||||
if (dev->num_slots > MAX_SLOTS)
|
||||
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;
|
||||
|
||||
ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, slot);
|
||||
last_reported_slot = slot;
|
||||
|
||||
for (axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||||
for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||||
if (axis == ABS_MT_SLOT ||
|
||||
!libevdev_has_event_code(dev, EV_ABS, axis))
|
||||
continue;
|
||||
|
||||
if (bit_is_set(slot_update, AXISBIT(slot, axis))) {
|
||||
ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_ABS, axis, *slot_value(dev, slot, axis));
|
||||
if (bit_is_set(changes[slot].axes, axis)) {
|
||||
/* We already sent the tracking id -1 in
|
||||
* 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;
|
||||
|
||||
if (dev->current_slot != last_reported_slot) {
|
||||
ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, dev->current_slot);
|
||||
}
|
||||
|
||||
#undef AXISBIT
|
||||
if (dev->current_slot != last_reported_slot)
|
||||
queue_push_event(dev, EV_ABS, ABS_MT_SLOT, dev->current_slot);
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
|
|
@ -783,11 +866,13 @@ read_more_events(struct libevdev *dev)
|
|||
|
||||
next = queue_next_element(dev);
|
||||
len = read(dev->fd, next, free_elem * sizeof(struct input_event));
|
||||
if (len < 0) {
|
||||
if (len < 0)
|
||||
return -errno;
|
||||
} else if (len > 0 && len % sizeof(struct input_event) != 0)
|
||||
|
||||
if (len > 0 && len % sizeof(struct input_event) != 0)
|
||||
return -EINVAL;
|
||||
else if (len > 0) {
|
||||
|
||||
if (len > 0) {
|
||||
int nev = len/sizeof(struct input_event);
|
||||
queue_set_num_elements(dev, queue_num_elements(dev) + nev);
|
||||
}
|
||||
|
|
@ -834,12 +919,35 @@ static int
|
|||
sync_state(struct libevdev *dev)
|
||||
{
|
||||
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
|
||||
* libevdev/libevdev.h */
|
||||
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))
|
||||
rc = sync_key_state(dev);
|
||||
if (libevdev_has_event_type(dev, EV_LED))
|
||||
|
|
@ -848,15 +956,13 @@ sync_state(struct libevdev *dev)
|
|||
rc = sync_sw_state(dev);
|
||||
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
||||
rc = sync_abs_state(dev);
|
||||
if (rc == 0 && dev->num_slots > -1 &&
|
||||
libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
||||
rc = sync_mt_state(dev, 1);
|
||||
if (rc == 0 && want_mt_sync)
|
||||
push_mt_sync_events(dev, changes, last_reported_slot);
|
||||
|
||||
dev->queue_nsync = queue_num_elements(dev);
|
||||
|
||||
if (dev->queue_nsync > 0) {
|
||||
ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_SYN, SYN_REPORT, 0);
|
||||
queue_push_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
dev->queue_nsync++;
|
||||
}
|
||||
|
||||
|
|
@ -890,7 +996,9 @@ update_mt_state(struct libevdev *dev, const struct input_event *e)
|
|||
}
|
||||
|
||||
return 0;
|
||||
} else if (dev->current_slot == -1)
|
||||
}
|
||||
|
||||
if (dev->current_slot == -1)
|
||||
return 1;
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -979,6 +1088,9 @@ sanitize_event(const struct libevdev *dev,
|
|||
struct input_event *ev,
|
||||
enum SyncState sync_state)
|
||||
{
|
||||
if (!libevdev_has_event_code(dev, ev->type, ev->code))
|
||||
return EVENT_FILTER_DISCARD;
|
||||
|
||||
if (unlikely(dev->num_slots > -1 &&
|
||||
libevdev_event_is_code(ev, EV_ABS, ABS_MT_SLOT) &&
|
||||
(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
|
||||
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 &&
|
||||
libevdev_event_is_code(ev, EV_ABS, ABS_MT_TRACKING_ID) &&
|
||||
((ev->value == -1 &&
|
||||
|
|
@ -1020,7 +1134,9 @@ libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event
|
|||
if (!dev->initialized) {
|
||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||
return -EBADF;
|
||||
} else if (dev->fd < 0)
|
||||
}
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
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.
|
||||
*/
|
||||
do {
|
||||
if (!(flags & LIBEVDEV_READ_FLAG_BLOCKING) ||
|
||||
queue_num_elements(dev) == 0) {
|
||||
if (queue_num_elements(dev) == 0) {
|
||||
rc = read_more_events(dev);
|
||||
if (rc < 0 && rc != -EAGAIN)
|
||||
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) {
|
||||
dev->queue_nsync--;
|
||||
rc = LIBEVDEV_READ_STATUS_SYNC;
|
||||
if (dev->queue_nsync == 0) {
|
||||
struct input_event next;
|
||||
if (dev->queue_nsync == 0)
|
||||
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:
|
||||
|
|
@ -1119,7 +1227,9 @@ libevdev_has_event_pending(struct libevdev *dev)
|
|||
if (!dev->initialized) {
|
||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||
return -EBADF;
|
||||
} else if (dev->fd < 0)
|
||||
}
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
if (queue_num_elements(dev) != 0)
|
||||
|
|
@ -1204,6 +1314,16 @@ libevdev_enable_property(struct libevdev *dev, unsigned int prop)
|
|||
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_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)) {
|
||||
*value = libevdev_get_event_value(dev, type, code);
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
*value = libevdev_get_slot_value(dev, slot, code);
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIBEVDEV_EXPORT int
|
||||
|
|
@ -1489,6 +1611,12 @@ libevdev_enable_event_code(struct libevdev *dev, unsigned int type,
|
|||
if (type == EV_ABS) {
|
||||
const struct input_absinfo *abs = data;
|
||||
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) {
|
||||
const int *value = data;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1524,7 +1661,9 @@ libevdev_kernel_set_abs_info(struct libevdev *dev, unsigned int code, const stru
|
|||
if (!dev->initialized) {
|
||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||
return -EBADF;
|
||||
} else if (dev->fd < 0)
|
||||
}
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
if (code > ABS_MAX)
|
||||
|
|
@ -1547,7 +1686,9 @@ libevdev_grab(struct libevdev *dev, enum libevdev_grab_mode grab)
|
|||
if (!dev->initialized) {
|
||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||
return -EBADF;
|
||||
} else if (dev->fd < 0)
|
||||
}
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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_property_get_name(unsigned int prop)
|
||||
{
|
||||
|
|
@ -1658,7 +1816,9 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...)
|
|||
if (!dev->initialized) {
|
||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||
return -EBADF;
|
||||
} else if (dev->fd < 0)
|
||||
}
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
memset(ev, 0, sizeof(ev));
|
||||
|
|
@ -1714,7 +1874,9 @@ libevdev_set_clock_id(struct libevdev *dev, int clockid)
|
|||
if (!dev->initialized) {
|
||||
log_bug(dev, "device not initialized. call libevdev_set_fd() first\n");
|
||||
return -EBADF;
|
||||
} else if (dev->fd < 0)
|
||||
}
|
||||
|
||||
if (dev->fd < 0)
|
||||
return -EBADF;
|
||||
|
||||
return ioctl(dev->fd, EVIOCSCLOCKID, &clockid) ? -errno : 0;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,26 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* 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.
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* 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
|
||||
|
|
@ -39,23 +42,29 @@ extern "C" {
|
|||
* the \ref ioctls through type-safe interfaces and provides functions to change
|
||||
* the appearance of the device.
|
||||
*
|
||||
* Development
|
||||
* ===========
|
||||
* The git repository is available here:
|
||||
*
|
||||
* - https://gitlab.freedesktop.org/libevdev/libevdev
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Handling events and SYN_DROPPED
|
||||
* ===============================
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* libevdev_next_event() and @ref syn_dropped for more information on how
|
||||
* SYN_DROPPED is handled.
|
||||
* `SYN_DROPPED` is handled.
|
||||
*
|
||||
* Signal safety
|
||||
* =============
|
||||
|
|
@ -78,7 +87,7 @@ extern "C" {
|
|||
*
|
||||
* libevdev does not handle the file descriptors directly, it merely uses
|
||||
* 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.
|
||||
*
|
||||
* Where does libevdev sit?
|
||||
|
|
@ -95,9 +104,10 @@ extern "C" {
|
|||
*
|
||||
* 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
|
||||
* too low in the stack.
|
||||
|
|
@ -135,14 +145,14 @@ extern "C" {
|
|||
* rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
||||
* if (rc == 0)
|
||||
* printf("Event: %s %s %d\n",
|
||||
* libevdev_get_event_type_name(ev.type),
|
||||
* libevdev_get_event_code_name(ev.type, ev.code),
|
||||
* libevdev_event_type_get_name(ev.type),
|
||||
* libevdev_event_code_get_name(ev.type, ev.code),
|
||||
* ev.value);
|
||||
* } while (rc == 1 || rc == 0 || rc == -EAGAIN);
|
||||
* @endcode
|
||||
*
|
||||
* 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
|
||||
* =========================================
|
||||
|
|
@ -153,25 +163,31 @@ extern "C" {
|
|||
* License information
|
||||
* ===================
|
||||
* 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
|
||||
* ==============
|
||||
* Please report bugs in the freedesktop.org bugzilla under the libevdev product:
|
||||
* https://bugs.freedesktop.org/enter_bug.cgi?product=libevdev
|
||||
* Please report bugs in the freedesktop.org GitLab instance:
|
||||
* https://gitlab.freedesktop.org/libevdev/libevdev/issues/
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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
|
||||
* 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
|
||||
* 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
|
||||
* events. The number of events between `SYN_REPORT` events is arbitrary and
|
||||
* depends on the hardware. An example event sequence may look like this:
|
||||
* @code
|
||||
* 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 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
|
||||
* 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
|
||||
* may look like this (note the missing/repeated events):
|
||||
* @code
|
||||
|
|
@ -210,19 +226,19 @@ extern "C" {
|
|||
* EV_SYN SYN_REPORT 0
|
||||
* @endcode
|
||||
*
|
||||
* A SYN_DROPPED event may be recieved at any time in the event sequence.
|
||||
* When a SYN_DROPPED event is received, the client must:
|
||||
* * discard all events since the last SYN_REPORT
|
||||
* * discard all events until including the next SYN_REPORT
|
||||
* A `SYN_DROPPED` event may be recieved at any time in the event sequence.
|
||||
* When a `SYN_DROPPED` event is received, the client must:
|
||||
* * discard all events since the last `SYN_REPORT`
|
||||
* * discard all events until including the next `SYN_REPORT`
|
||||
* These event are part of incomplete event frames.
|
||||
*
|
||||
* Synchronizing the state of the device
|
||||
* =====================================
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* retrieved state and handle the deltas accordingly.
|
||||
* 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
|
||||
* @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
|
||||
* 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
|
||||
* 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
|
||||
* active slot.
|
||||
* 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_SYN SYN_REPORT 0
|
||||
* @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
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* generating multiple events:
|
||||
* * for each slot on the device, libevdev generates an
|
||||
* 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
|
||||
* `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
|
||||
* 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
|
||||
* * 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:
|
||||
* @code
|
||||
|
|
@ -278,26 +294,26 @@ extern "C" {
|
|||
* EV_ABS ABS_MT_SLOT 1
|
||||
* EV_SYN SYN_REPORT 0
|
||||
* @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.
|
||||
*
|
||||
* Synchronizing ABS_MT_TRACKING_ID
|
||||
* ================================
|
||||
*
|
||||
* 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
|
||||
* 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 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
|
||||
* 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
|
||||
* 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
|
||||
* events if the ABS_MT_TRACKING_ID has changed:
|
||||
* * if the ABS_MT_TRACKING_ID was valid and is -1, libevdev enqueues an
|
||||
* ABS_MT_TRACKING_ID event with value -1.
|
||||
* * 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.
|
||||
* * 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
|
||||
* another ABS_MT_TRACKING_ID event with the new value.
|
||||
* the `ABS_MT_TRACKING_ID`. libevdev simplifies this by emulating extra
|
||||
* events if the `ABS_MT_TRACKING_ID` has changed:
|
||||
* * if the `ABS_MT_TRACKING_ID` was valid and is -1, libevdev enqueues an
|
||||
* `ABS_MT_TRACKING_ID` event with value -1.
|
||||
* * 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.
|
||||
* * 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
|
||||
* another `ABS_MT_TRACKING_ID` event with the new value.
|
||||
*
|
||||
* An example event sequence for such a sync may look like this:
|
||||
* @code
|
||||
|
|
@ -318,14 +334,14 @@ extern "C" {
|
|||
* EV_SYN SYN_REPORT 0
|
||||
* @endcode
|
||||
* 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
|
||||
* in slot 1 maintained the same ABS_MT_TRACKING_ID and only updated the
|
||||
* 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
|
||||
* coordinates. Slot 1 is the currently active slot.
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* kernel | userspace
|
||||
|
|
@ -349,7 +365,7 @@ extern "C" {
|
|||
* @endcode
|
||||
* If such an event sequence occurs, libevdev will send all updated axes
|
||||
* 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:
|
||||
* @code
|
||||
* EV_ABS ABS_MT_SLOT 0 ← LIBEVDEV_READ_FLAG_NORMAL
|
||||
|
|
@ -375,15 +391,15 @@ extern "C" {
|
|||
* 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
|
||||
* 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
|
||||
* appended to the buffer until it is either read by the client, or filled
|
||||
* again, at which point the sequence repeats.
|
||||
*
|
||||
* 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,
|
||||
* i.e. the state after all these events have been processed. For example,
|
||||
* assume the buffer contains the following sequence:
|
||||
|
|
@ -405,10 +421,10 @@ extern "C" {
|
|||
* @endcode
|
||||
* 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
|
||||
* 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
|
||||
* by libevdev is:
|
||||
* @code
|
||||
|
|
@ -433,7 +449,7 @@ extern "C" {
|
|||
* Minimum requirements
|
||||
* ====================
|
||||
* 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
|
||||
* ==============================
|
||||
|
|
@ -442,28 +458,28 @@ extern "C" {
|
|||
* The list of event names is compiled at build-time, any events not defined
|
||||
* at build time will not resolve. Specifically,
|
||||
* 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.
|
||||
*
|
||||
* Input properties
|
||||
* ================
|
||||
* 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
|
||||
* property has been manually set with libevdev_enable_property().
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
|
@ -484,11 +500,11 @@ extern "C" {
|
|||
* <dd>supported, see libevdev_enable_event_code()</dd>
|
||||
* <dt>EVIOCGKEYCODE:</dt>
|
||||
* <dd>currently not supported</dd>
|
||||
* <dt>EVIOCGKEYCODE:</dt>
|
||||
* <dd>currently not supported</dd>
|
||||
* <dt>EVIOCSKEYCODE:</dt>
|
||||
* <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>
|
||||
* <dt>EVIOCGNAME:</dt>
|
||||
* <dd>supported, see libevdev_get_name()</dd>
|
||||
|
|
@ -528,6 +544,10 @@ extern "C" {
|
|||
* <dt>EVIOCREVOKE:</dt>
|
||||
* <dd>currently not supported, see
|
||||
* 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>
|
||||
*
|
||||
*/
|
||||
|
|
@ -562,7 +582,7 @@ extern "C" {
|
|||
* [Check unit testing framework](http://check.sourceforge.net/). Tests are
|
||||
* 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
|
||||
* CONFIG_INPUT_UINPUT enabled.
|
||||
* `CONFIG_INPUT_UINPUT` enabled.
|
||||
*
|
||||
* To run a specific suite only:
|
||||
*
|
||||
|
|
@ -618,7 +638,7 @@ extern "C" {
|
|||
* return ENOMEM;
|
||||
*
|
||||
* err = libevdev_set_fd(dev, fd);
|
||||
* if (err < 0) {
|
||||
* if (err < 0)
|
||||
* printf("Failed (errno %d): %s\n", -err, strerror(-err));
|
||||
*
|
||||
* libevdev_free(dev);
|
||||
|
|
@ -655,9 +675,9 @@ extern "C" {
|
|||
/**
|
||||
* @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
|
||||
* 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.
|
||||
* 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
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* meaning, matching the axis names in linux/input.h. Some devices merely
|
||||
* export a number of axes beyond the available axis list. For those
|
||||
* devices, the multitouch information is invalid. Specfically, if a device
|
||||
* provides the ABS_MT_SLOT axis AND also the (ABS_MT_SLOT - 1) axis, the
|
||||
* devices, the multitouch information is invalid. Specifically, if a device
|
||||
* provides the `ABS_MT_SLOT` axis AND also the `ABS_RESERVED` axis, the
|
||||
* 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
|
||||
* other EV_ABS axes.
|
||||
* available and the `ABS_MT` axis range for these devices is treated as all
|
||||
* other `EV_ABS` axes.
|
||||
*
|
||||
* Note that because of limitations in the kernel API, such fake multitouch
|
||||
* devices can not be reliably synched after a SYN_DROPPED event. libevdev
|
||||
* ignores all ABS_MT axis values during the sync process and instead
|
||||
* devices can not be reliably synced after a `SYN_DROPPED` event. libevdev
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
|
|
@ -956,10 +976,14 @@ enum libevdev_grab_mode {
|
|||
* Grabbing an already grabbed device, or ungrabbing an ungrabbed device is
|
||||
* 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 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.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* 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().
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
|
@ -1276,7 +1305,9 @@ int libevdev_get_id_vendor(const struct libevdev *dev);
|
|||
* @param vendor_id The vendor ID to assign to this device
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
|
@ -1298,7 +1329,9 @@ int libevdev_get_id_bustype(const struct libevdev *dev);
|
|||
* @param bustype The bustype to assign to this device
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
|
@ -1320,7 +1353,9 @@ int libevdev_get_id_version(const struct libevdev *dev);
|
|||
* @param version The version to assign to this device
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
|
@ -1477,8 +1522,7 @@ const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, un
|
|||
* the event.
|
||||
*
|
||||
* 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
|
||||
* libevdev_get_slot_value() instead.
|
||||
* event code is undefined. Use libevdev_get_slot_value() instead.
|
||||
*
|
||||
* @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.)
|
||||
|
|
@ -1518,9 +1562,11 @@ int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsi
|
|||
* @param value The new value to set
|
||||
*
|
||||
* @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
|
||||
* allowed limits for the given type, or the type cannot be set, or the
|
||||
* value is not permitted for the given code.
|
||||
* @retval -1
|
||||
* - the device does not have the event type or code enabled, or
|
||||
* - 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_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
|
||||
*
|
||||
* @return 0 on success, or -1 on failure.
|
||||
* @retval -1 the device does not have the event code enabled, or 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.
|
||||
* @retval -1
|
||||
* - the device does not have the event code enabled, or
|
||||
* - 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_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 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
|
||||
|
|
@ -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 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
|
||||
|
|
@ -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 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
|
||||
|
|
@ -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 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
|
||||
|
|
@ -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 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
|
||||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
|
|
@ -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,
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,23 +1,6 @@
|
|||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* 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 {
|
||||
|
|
@ -112,3 +95,29 @@ global:
|
|||
local:
|
||||
*;
|
||||
} 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
|
||||
# Prints C header files or Python files that can be used as
|
||||
# mapping and lookup tables.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
class Bits(object):
|
||||
pass
|
||||
def __init__(self):
|
||||
self.max_codes = {}
|
||||
|
||||
|
||||
prefixes = [
|
||||
"EV_",
|
||||
"REL_",
|
||||
"ABS_",
|
||||
"KEY_",
|
||||
"BTN_",
|
||||
"LED_",
|
||||
"SND_",
|
||||
"MSC_",
|
||||
"SW_",
|
||||
"FF_",
|
||||
"SYN_",
|
||||
"REP_",
|
||||
"INPUT_PROP_",
|
||||
"EV_",
|
||||
"REL_",
|
||||
"ABS_",
|
||||
"KEY_",
|
||||
"BTN_",
|
||||
"LED_",
|
||||
"SND_",
|
||||
"MSC_",
|
||||
"SW_",
|
||||
"FF_",
|
||||
"SYN_",
|
||||
"REP_",
|
||||
"INPUT_PROP_",
|
||||
"MT_TOOL_",
|
||||
]
|
||||
|
||||
blacklist = [
|
||||
"EV_VERSION",
|
||||
"BTN_MISC",
|
||||
"BTN_MOUSE",
|
||||
"BTN_JOYSTICK",
|
||||
"BTN_GAMEPAD",
|
||||
"BTN_DIGI",
|
||||
"BTN_WHEEL",
|
||||
"BTN_TRIGGER_HAPPY"
|
||||
duplicates = [
|
||||
"EV_VERSION",
|
||||
"BTN_MISC",
|
||||
"BTN_MOUSE",
|
||||
"BTN_JOYSTICK",
|
||||
"BTN_GAMEPAD",
|
||||
"BTN_DIGI",
|
||||
"BTN_WHEEL",
|
||||
"BTN_TRIGGER_HAPPY",
|
||||
"SW_MAX",
|
||||
"REP_MAX",
|
||||
]
|
||||
|
||||
btn_additional = [
|
||||
[0, "BTN_A"],
|
||||
[0, "BTN_B"],
|
||||
[0, "BTN_X"],
|
||||
[0, "BTN_Y"],
|
||||
[0, "BTN_A"],
|
||||
[0, "BTN_B"],
|
||||
[0, "BTN_X"],
|
||||
[0, "BTN_Y"],
|
||||
]
|
||||
|
||||
names = [
|
||||
"REL_",
|
||||
"ABS_",
|
||||
"KEY_",
|
||||
"BTN_",
|
||||
"LED_",
|
||||
"SND_",
|
||||
"MSC_",
|
||||
"SW_",
|
||||
"FF_",
|
||||
"SYN_",
|
||||
"REP_",
|
||||
code_prefixes = [
|
||||
"REL_",
|
||||
"ABS_",
|
||||
"KEY_",
|
||||
"BTN_",
|
||||
"LED_",
|
||||
"SND_",
|
||||
"MSC_",
|
||||
"SW_",
|
||||
"FF_",
|
||||
"SYN_",
|
||||
"REP_",
|
||||
]
|
||||
|
||||
|
||||
def print_bits(bits, prefix):
|
||||
if not hasattr(bits, prefix):
|
||||
return
|
||||
print("static const char * const %s_map[%s_MAX + 1] = {" % (prefix, prefix.upper()))
|
||||
for val, name in list(getattr(bits, prefix).items()):
|
||||
print(" [%s] = \"%s\"," % (name, name))
|
||||
if prefix == "key":
|
||||
for val, name in list(getattr(bits, "btn").items()):
|
||||
print(" [%s] = \"%s\"," % (name, name))
|
||||
print("};")
|
||||
print("")
|
||||
if not hasattr(bits, prefix):
|
||||
return
|
||||
print("static const char * const %s_map[%s_MAX + 1] = {" % (prefix, prefix.upper()))
|
||||
for val, name in sorted(list(getattr(bits, prefix).items())):
|
||||
print(" [%s] = \"%s\"," % (name, name))
|
||||
if prefix == "key":
|
||||
for val, name in sorted(list(getattr(bits, "btn").items())):
|
||||
print(" [%s] = \"%s\"," % (name, name))
|
||||
print("};")
|
||||
print("")
|
||||
|
||||
|
||||
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:
|
||||
if prefix == "BTN_" or prefix == "EV_" or prefix == "INPUT_PROP_":
|
||||
continue
|
||||
print(" [EV_%s] = %s_map," % (prefix[:-1], prefix[:-1].lower()))
|
||||
for prefix in prefixes:
|
||||
if prefix in ["BTN_", "EV_", "INPUT_PROP_", "MT_TOOL_"]:
|
||||
continue
|
||||
print(" [EV_%s] = %s_map," % (prefix[:-1], prefix[:-1].lower()))
|
||||
|
||||
print("};")
|
||||
print("")
|
||||
print("};")
|
||||
print("")
|
||||
|
||||
print("#if __clang__")
|
||||
print("#pragma clang diagnostic push")
|
||||
print("#pragma clang diagnostic ignored \"-Winitializer-overrides\"")
|
||||
print("#else")
|
||||
print("#pragma GCC diagnostic push")
|
||||
print("#pragma GCC diagnostic ignored \"-Woverride-init\"")
|
||||
print("#endif")
|
||||
print("static const int ev_max[EV_MAX + 1] = {")
|
||||
print(" [0 ... EV_MAX] = -1,")
|
||||
for prefix in prefixes:
|
||||
if prefix == "BTN_" or prefix == "EV_" or prefix == "INPUT_PROP_":
|
||||
continue
|
||||
print(" [EV_%s] = %s_MAX," % (prefix[:-1], prefix[:-1]))
|
||||
print("};")
|
||||
print("#if __clang__")
|
||||
print("#pragma clang diagnostic pop /* \"-Winitializer-overrides\" */")
|
||||
print("#else")
|
||||
print("#pragma GCC diagnostic pop /* \"-Woverride-init\" */")
|
||||
print("#endif");
|
||||
print("")
|
||||
print("#if __clang__")
|
||||
print("#pragma clang diagnostic push")
|
||||
print("#pragma clang diagnostic ignored \"-Winitializer-overrides\"")
|
||||
print("#elif __GNUC__")
|
||||
print("#pragma GCC diagnostic push")
|
||||
print("#pragma GCC diagnostic ignored \"-Woverride-init\"")
|
||||
print("#endif")
|
||||
print("static const int ev_max[EV_MAX + 1] = {")
|
||||
for val in range(bits.max_codes["EV_MAX"] + 1):
|
||||
if val in bits.ev:
|
||||
prefix = bits.ev[val][3:]
|
||||
if prefix + "_" in prefixes:
|
||||
print(" %s_MAX," % prefix)
|
||||
continue
|
||||
print(" -1,")
|
||||
print("};")
|
||||
print("#if __clang__")
|
||||
print("#pragma clang diagnostic pop /* \"-Winitializer-overrides\" */")
|
||||
print("#elif __GNUC__")
|
||||
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):
|
||||
if not hasattr(bits, prefix):
|
||||
return
|
||||
if not hasattr(bits, prefix):
|
||||
return
|
||||
|
||||
names = list(getattr(bits, prefix).items())
|
||||
if prefix == "btn":
|
||||
names = names + btn_additional;
|
||||
names = sorted(list(getattr(bits, prefix).items()))
|
||||
if prefix == "btn":
|
||||
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):
|
||||
print("struct name_entry {")
|
||||
print(" const char *name;")
|
||||
print(" unsigned int value;")
|
||||
print("};")
|
||||
print("")
|
||||
print("static const struct name_entry ev_names[] = {")
|
||||
print_lookup(bits, "ev")
|
||||
print("};")
|
||||
print("")
|
||||
print("struct name_entry {")
|
||||
print(" const char *name;")
|
||||
print(" unsigned int value;")
|
||||
print("};")
|
||||
print("")
|
||||
print("static const struct name_entry tool_type_names[] = {")
|
||||
print_lookup(bits, "mt_tool")
|
||||
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):
|
||||
print("/* THIS FILE IS GENERATED, DO NOT EDIT */")
|
||||
print("")
|
||||
print("#ifndef EVENT_NAMES_H")
|
||||
print("#define EVENT_NAMES_H")
|
||||
print("")
|
||||
print("/* THIS FILE IS GENERATED, DO NOT EDIT */")
|
||||
print("")
|
||||
print("#ifndef EVENT_NAMES_H")
|
||||
print("#define EVENT_NAMES_H")
|
||||
print("")
|
||||
|
||||
for prefix in prefixes:
|
||||
if prefix == "BTN_":
|
||||
continue
|
||||
print_bits(bits, prefix[:-1].lower())
|
||||
for prefix in prefixes:
|
||||
if prefix == "BTN_":
|
||||
continue
|
||||
print_bits(bits, prefix[:-1].lower())
|
||||
|
||||
print_map(bits)
|
||||
print_lookup_table(bits)
|
||||
print_map(bits)
|
||||
print_lookup_table(bits)
|
||||
|
||||
print("#endif /* EVENT_NAMES_H */")
|
||||
|
||||
print("#endif /* EVENT_NAMES_H */")
|
||||
|
||||
def parse_define(bits, line):
|
||||
m = re.match(r"^#define\s+(\w+)\s+(\w+)", line)
|
||||
if m == None:
|
||||
return
|
||||
m = re.match(r"^#define\s+(\w+)\s+(\w+)", line)
|
||||
if m is None:
|
||||
return
|
||||
|
||||
name = m.group(1)
|
||||
name = m.group(1)
|
||||
|
||||
if name in blacklist:
|
||||
return
|
||||
try:
|
||||
value = int(m.group(2), 0)
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
try:
|
||||
value = int(m.group(2), 0)
|
||||
except ValueError:
|
||||
return
|
||||
for prefix in prefixes:
|
||||
if not name.startswith(prefix):
|
||||
continue
|
||||
|
||||
for prefix in prefixes:
|
||||
if not name.startswith(prefix):
|
||||
continue
|
||||
if name.endswith("_MAX"):
|
||||
bits.max_codes[name] = value
|
||||
|
||||
attrname = prefix[:-1].lower()
|
||||
if name in duplicates:
|
||||
return
|
||||
|
||||
if not hasattr(bits, attrname):
|
||||
setattr(bits, attrname, {})
|
||||
b = getattr(bits, attrname)
|
||||
b[value] = name
|
||||
attrname = prefix[:-1].lower()
|
||||
|
||||
def parse(fp):
|
||||
bits = Bits()
|
||||
if not hasattr(bits, attrname):
|
||||
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):
|
||||
print("Usage: cat <files> | %s" % prog)
|
||||
print("Usage: %s <files>".format(prog))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 1:
|
||||
usage(sys.argv[0])
|
||||
sys.exit(2)
|
||||
if len(sys.argv) <= 1:
|
||||
usage(sys.argv[0])
|
||||
sys.exit(2)
|
||||
|
||||
bits = parse(sys.stdin)
|
||||
print_mapping_table(bits)
|
||||
from itertools import chain
|
||||
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
|
||||
|
||||
check_local_deps =
|
||||
clean_local_deps =
|
||||
|
||||
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:
|
||||
|
||||
|
|
@ -33,15 +38,7 @@ noinst_PROGRAMS += $(run_tests)
|
|||
|
||||
TESTS = $(run_tests)
|
||||
|
||||
libevdev_sources = $(top_srcdir)/libevdev/libevdev.c \
|
||||
$(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) \
|
||||
common_sources = \
|
||||
test-common-uinput.c \
|
||||
test-common-uinput.h \
|
||||
test-common.c \
|
||||
|
|
@ -51,67 +48,58 @@ common_sources = $(libevdev_sources) \
|
|||
AM_CPPFLAGS += $(CHECK_CFLAGS) $(GCOV_CFLAGS)
|
||||
AM_LDFLAGS += $(GCOV_LDFLAGS)
|
||||
|
||||
test_libevdev_SOURCES = \
|
||||
test_event_codes_SOURCES = \
|
||||
test-main.c \
|
||||
test-event-names.c \
|
||||
test-event-codes.c \
|
||||
test-libevdev-init.c \
|
||||
test-libevdev-has-event.c \
|
||||
test-event-names.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-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 \
|
||||
$(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-main.c \
|
||||
test-kernel.c \
|
||||
$(common_sources)
|
||||
|
||||
test_kernel_CFLAGS = -I$(top_srcdir)
|
||||
test_kernel_LDADD = $(CHECK_LIBS)
|
||||
|
||||
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
|
||||
test_kernel_LDADD = $(CHECK_LIBS) $(top_builddir)/libevdev/libevdev.la
|
||||
|
||||
if GCOV_ENABLED
|
||||
|
||||
CLEANFILES = gcov-report.txt
|
||||
CLEANFILES = gcov-reports/*.gcov gcov-reports/summary.txt *.gcno *.gcda
|
||||
|
||||
gcov-clean:
|
||||
@rm -f *.gcov
|
||||
gcov-report: generate-gcov-report.sh
|
||||
$(AM_V_GEN)$(srcdir)/generate-gcov-report.sh gcov-reports $(top_builddir)/libevdev $(builddir)
|
||||
|
||||
gcov-report.txt: gcov-clean check-TESTS
|
||||
$(AM_V_GEN)(rm -rf $@; \
|
||||
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
|
||||
gcov: gcov-report
|
||||
@cat gcov-reports/summary.txt
|
||||
|
||||
check_local_deps += gcov
|
||||
clean_local_deps += gcov-clean
|
||||
|
||||
else
|
||||
|
||||
|
|
@ -121,37 +109,22 @@ gcov-report.txt:
|
|||
gcov:
|
||||
@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
|
||||
|
||||
if ENABLE_STATIC_SYMBOL_LEAKS_TEST
|
||||
# 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"
|
||||
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 \
|
||||
)
|
||||
static-symbol-leaks: test-static-link test-static-symbols-leak.sh
|
||||
$(AM_V_GEN) $(srcdir)/test-static-symbols-leak.sh $(builddir)
|
||||
|
||||
check_local_deps += static-symbol-leaks
|
||||
|
||||
endif # HAVE_NM
|
||||
|
||||
EXTRA_DIST = valgrind.suppressions generate-gcov-report.sh test-static-symbols-leak.sh
|
||||
|
||||
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.
|
||||
*
|
||||
* 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 <unistd.h>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#define DEFAULT_IDS NULL
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -89,6 +72,7 @@ void test_create_abs_device(struct uinput_device **uidev_return,
|
|||
|
||||
va_start(args, abs);
|
||||
rc = uinput_device_set_event_bits_v(uidev, args);
|
||||
ck_assert_msg(rc == 0, "Failed to set uinput bits");
|
||||
va_end(args);
|
||||
|
||||
while (--nabs >= 0) {
|
||||
|
|
|
|||
|
|
@ -1,37 +1,57 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#ifndef _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 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"
|
||||
|
||||
#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,
|
||||
struct libevdev **dev,
|
||||
...);
|
||||
|
|
@ -51,4 +71,23 @@ void test_logfunc_ignore_error(enum libevdev_log_priority priority,
|
|||
const char *file, int line,
|
||||
const char *func,
|
||||
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_ */
|
||||
|
|
|
|||
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>
|
||||
*
|
||||
* 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"
|
||||
|
||||
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_KEY"), EV_KEY);
|
||||
|
|
@ -43,7 +26,7 @@ START_TEST(test_type_codes)
|
|||
}
|
||||
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);
|
||||
|
|
@ -55,7 +38,42 @@ START_TEST(test_type_invalid)
|
|||
}
|
||||
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_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_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_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);
|
||||
}
|
||||
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_CNT, "CNT_FAKE"), -1);
|
||||
|
|
@ -99,6 +141,76 @@ START_TEST(test_key_invalid)
|
|||
}
|
||||
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)
|
||||
{
|
||||
struct prop {
|
||||
|
|
@ -131,25 +243,26 @@ START_TEST(test_properties_invalid)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
event_code_suite(void)
|
||||
TEST_SUITE(event_code_suite)
|
||||
{
|
||||
Suite *s = suite_create("Event codes");
|
||||
|
||||
TCase *tc = tcase_create("type tests");
|
||||
tcase_add_test(tc, test_type_codes);
|
||||
tcase_add_test(tc, test_type_invalid);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_type_names);
|
||||
add_test(s, test_type_names_invalid);
|
||||
add_test(s, test_type_name_lookup);
|
||||
add_test(s, test_type_name_lookup_invalid);
|
||||
|
||||
tc = tcase_create("key tests");
|
||||
tcase_add_test(tc, test_key_codes);
|
||||
tcase_add_test(tc, test_key_invalid);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_code_names);
|
||||
add_test(s, test_code_name_lookup);
|
||||
add_test(s, test_code_names_invalid);
|
||||
add_test(s, test_code_name_lookup_invalid);
|
||||
add_test(s, test_code_names_max);
|
||||
|
||||
tc = tcase_create("property tests");
|
||||
tcase_add_test(tc, test_properties);
|
||||
tcase_add_test(tc, test_properties_invalid);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_value_names);
|
||||
add_test(s, test_value_names_invalid);
|
||||
|
||||
add_test(s, test_properties);
|
||||
add_test(s, test_properties_invalid);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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"
|
||||
|
||||
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_FF, FF_MAX + 1) == 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
|
||||
|
||||
|
|
@ -143,6 +127,15 @@ START_TEST(test_code_snd_name)
|
|||
}
|
||||
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)
|
||||
{
|
||||
/* 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_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_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
|
||||
|
||||
|
|
@ -191,6 +185,35 @@ START_TEST(test_code_syn_name)
|
|||
}
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
Suite *
|
||||
event_name_suite(void)
|
||||
TEST_SUITE(event_name_suite)
|
||||
{
|
||||
Suite *s = suite_create("Event names");
|
||||
|
||||
TCase *tc = tcase_create("type limits");
|
||||
tcase_add_test(tc, test_limits);
|
||||
tcase_add_test(tc, test_event_type_max);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_limits);
|
||||
add_test(s, test_event_type_max);
|
||||
|
||||
tc = tcase_create("type names");
|
||||
tcase_add_test(tc, test_type_name);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_type_name);
|
||||
|
||||
tc = tcase_create("code names");
|
||||
tcase_add_test(tc, test_code_abs_name);
|
||||
tcase_add_test(tc, test_code_rel_name);
|
||||
tcase_add_test(tc, test_code_key_name);
|
||||
tcase_add_test(tc, test_code_led_name);
|
||||
tcase_add_test(tc, test_code_snd_name);
|
||||
tcase_add_test(tc, test_code_msc_name);
|
||||
tcase_add_test(tc, test_code_sw_name);
|
||||
tcase_add_test(tc, test_code_ff_name);
|
||||
tcase_add_test(tc, test_code_syn_name);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_code_abs_name);
|
||||
add_test(s, test_code_rel_name);
|
||||
add_test(s, test_code_key_name);
|
||||
add_test(s, test_code_led_name);
|
||||
add_test(s, test_code_snd_name);
|
||||
add_test(s, test_code_rep_name);
|
||||
add_test(s, test_code_msc_name);
|
||||
add_test(s, test_code_sw_name);
|
||||
add_test(s, test_code_ff_name);
|
||||
add_test(s, test_code_syn_name);
|
||||
|
||||
tc = tcase_create("prop names");
|
||||
tcase_add_test(tc, test_prop_name);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_value_name);
|
||||
add_test(s, test_prop_name);
|
||||
|
||||
tc = tcase_create("event values");
|
||||
tcase_add_test(tc, test_event_type);
|
||||
tcase_add_test(tc, test_event_code);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_event_type);
|
||||
add_test(s, test_event_code);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <libevdev/libevdev-int.h>
|
||||
#include "test-common.h"
|
||||
|
|
@ -33,9 +16,6 @@ START_TEST(test_queue_alloc)
|
|||
rc = queue_alloc(&dev, 0);
|
||||
ck_assert_int_eq(rc, -ENOMEM);
|
||||
|
||||
rc = queue_alloc(&dev, ULONG_MAX);
|
||||
ck_assert_int_eq(rc, -ENOMEM);
|
||||
|
||||
rc = queue_alloc(&dev, 100);
|
||||
ck_assert_int_eq(rc, 0);
|
||||
|
||||
|
|
@ -329,8 +309,7 @@ START_TEST(test_queue_set_num_elements)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
queue_suite(void)
|
||||
TEST_SUITE(queue_suite)
|
||||
{
|
||||
Suite *s = suite_create("Event queue");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <inttypes.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_SYN, SYN_REPORT, 0);
|
||||
|
||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1);
|
||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
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);
|
||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||
rc = libevdev_next_event(dev2, LIBEVDEV_READ_FLAG_NORMAL, &ev2);
|
||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
||||
|
||||
ck_assert_int_eq(ev1.type, ev2.type);
|
||||
ck_assert_int_eq(ev1.code, ev2.code);
|
||||
ck_assert_int_eq(ev1.value, ev2.value);
|
||||
ck_assert_int_eq(ev1.type, ev2.type);
|
||||
ck_assert_int_eq(ev1.code, ev2.code);
|
||||
ck_assert_int_eq(ev1.value, ev2.value);
|
||||
}
|
||||
|
||||
/* revoke first device, expect it closed, second device still open */
|
||||
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));
|
||||
|
||||
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);
|
||||
ck_assert_int_eq(rc, -ENODEV);
|
||||
|
||||
|
|
@ -160,26 +148,13 @@ out:
|
|||
}
|
||||
END_TEST
|
||||
|
||||
int main(int argc, char **argv)
|
||||
TEST_SUITE_ROOT_PRIVILEGES(kernel)
|
||||
{
|
||||
SRunner *sr;
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
int failed;
|
||||
Suite *s = suite_create("kernel");
|
||||
|
||||
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");
|
||||
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;
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <errno.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -117,6 +100,14 @@ START_TEST(test_event_codes)
|
|||
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);
|
||||
|
||||
for (code = 1; code < max; code += 10) {
|
||||
|
|
@ -125,10 +116,11 @@ START_TEST(test_event_codes)
|
|||
test_create_abs_device(&uidev, &dev,
|
||||
1, &abs,
|
||||
-1);
|
||||
} else
|
||||
} else {
|
||||
test_create_device(&uidev, &dev,
|
||||
*evbit, code,
|
||||
-1);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
@ -249,7 +241,7 @@ START_TEST(test_input_props)
|
|||
struct uinput_device* uidev;
|
||||
struct libevdev *dev;
|
||||
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);
|
||||
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 libevdev *dev;
|
||||
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();
|
||||
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_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);
|
||||
libevdev_free(dev);
|
||||
}
|
||||
|
|
@ -318,12 +317,14 @@ START_TEST(test_slot_init_value)
|
|||
const int nabs = 6;
|
||||
int i;
|
||||
int fd;
|
||||
struct input_absinfo abs[] = { { ABS_X, 0, 1000 },
|
||||
{ ABS_Y, 0, 1000 },
|
||||
{ ABS_MT_POSITION_X, 0, 1000 },
|
||||
{ ABS_MT_POSITION_Y, 0, 1000 },
|
||||
{ ABS_MT_TRACKING_ID, -1, 2 },
|
||||
{ ABS_MT_SLOT, 0, 1 }};
|
||||
struct input_absinfo abs[] = {
|
||||
{ .value = ABS_X, .minimum = 0, .maximum = 1000 },
|
||||
{ .value = ABS_Y, .minimum = 0, .maximum = 1000 },
|
||||
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 1000 },
|
||||
{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 1000 },
|
||||
{ .value = ABS_MT_TRACKING_ID, .minimum = -1, .maximum = 2 },
|
||||
{ .value = ABS_MT_SLOT, .minimum = 0, .maximum = 1 }
|
||||
};
|
||||
|
||||
uidev = uinput_device_new(TEST_DEVICE_NAME);
|
||||
|
||||
|
|
@ -371,10 +372,12 @@ START_TEST(test_no_slots)
|
|||
{
|
||||
struct uinput_device* uidev;
|
||||
struct libevdev *dev;
|
||||
struct input_absinfo abs[] = { { ABS_X, 0, 2 },
|
||||
{ ABS_Y, 0, 2 },
|
||||
{ ABS_MT_POSITION_X, 0, 2 },
|
||||
{ ABS_MT_POSITION_Y, 0, 2 }};
|
||||
struct input_absinfo abs[] = {
|
||||
{ .value = ABS_X, .minimum = 0, .maximum = 2 },
|
||||
{ .value = ABS_Y, .minimum = 0, .maximum = 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,
|
||||
-1);
|
||||
|
|
@ -392,11 +395,13 @@ START_TEST(test_slot_number)
|
|||
struct uinput_device* uidev;
|
||||
struct libevdev *dev;
|
||||
const int nslots = 4;
|
||||
struct input_absinfo abs[] = { { ABS_X, 0, 2 },
|
||||
{ ABS_Y, 0, 2 },
|
||||
{ ABS_MT_POSITION_X, 0, 2 },
|
||||
{ ABS_MT_POSITION_Y, 0, 2 },
|
||||
{ ABS_MT_SLOT, 0, nslots - 1 }};
|
||||
struct input_absinfo abs[] = {
|
||||
{ .value = ABS_X, .minimum = 0, .maximum = 2 },
|
||||
{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
|
||||
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
|
||||
{ .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,
|
||||
-1);
|
||||
|
|
@ -415,12 +420,14 @@ START_TEST(test_invalid_mt_device)
|
|||
struct libevdev *dev;
|
||||
const int nslots = 4;
|
||||
int value;
|
||||
struct input_absinfo abs[] = { { ABS_X, 0, 2 },
|
||||
{ ABS_Y, 0, 2 },
|
||||
{ ABS_MT_POSITION_X, 0, 2 },
|
||||
{ ABS_MT_POSITION_Y, 0, 2 },
|
||||
{ ABS_MT_SLOT - 1, 0, 2 },
|
||||
{ ABS_MT_SLOT, 0, nslots - 1 }};
|
||||
struct input_absinfo abs[] = {
|
||||
{ .value = ABS_X, .minimum = 0, .maximum = 2 },
|
||||
{ .value = ABS_Y, .minimum = 0, .maximum = 2 },
|
||||
{ .value = ABS_MT_POSITION_X, .minimum = 0, .maximum = 2 },
|
||||
{ .value = ABS_MT_POSITION_Y, .minimum = 0, .maximum = 2 },
|
||||
{ .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,
|
||||
-1);
|
||||
|
|
@ -732,7 +739,7 @@ START_TEST(test_device_enable_bit)
|
|||
{
|
||||
struct uinput_device* uidev;
|
||||
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;
|
||||
|
||||
test_create_abs_device(&uidev, &dev, 1, &abs,
|
||||
|
|
@ -776,7 +783,7 @@ START_TEST(test_device_enable_bit_invalid)
|
|||
{
|
||||
struct uinput_device* uidev;
|
||||
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);
|
||||
|
|
@ -802,7 +809,10 @@ START_TEST(test_device_disable_bit)
|
|||
struct uinput_device* uidev;
|
||||
struct libevdev *dev, *dev2;
|
||||
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,
|
||||
2, abs,
|
||||
|
|
@ -848,7 +858,7 @@ START_TEST(test_device_disable_bit_invalid)
|
|||
{
|
||||
struct uinput_device* uidev;
|
||||
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);
|
||||
|
||||
|
|
@ -1142,61 +1152,44 @@ START_TEST(test_led_same)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
libevdev_has_event_test(void)
|
||||
TEST_SUITE_ROOT_PRIVILEGES(has_events)
|
||||
{
|
||||
Suite *s = suite_create("libevdev_has_event tests");
|
||||
|
||||
TCase *tc = tcase_create("event type");
|
||||
tcase_add_test(tc, test_ev_bit_limits);
|
||||
tcase_add_test(tc, test_has_ev_bit);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_ev_bit_limits);
|
||||
add_test(s, test_has_ev_bit);
|
||||
|
||||
tc = tcase_create("event codes");
|
||||
tcase_add_test(tc, test_event_codes);
|
||||
tcase_add_test(tc, test_event_code_limits);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_event_codes);
|
||||
add_test(s, test_event_code_limits);
|
||||
|
||||
tc = tcase_create("ev_rep");
|
||||
tcase_add_test(tc, test_ev_rep);
|
||||
tcase_add_test(tc, test_ev_rep_values);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_ev_rep);
|
||||
add_test(s, test_ev_rep_values);
|
||||
|
||||
tc = tcase_create("input properties");
|
||||
tcase_add_test(tc, test_input_props);
|
||||
tcase_add_test(tc, test_set_input_props);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_input_props);
|
||||
add_test(s, test_set_input_props);
|
||||
|
||||
tc = tcase_create("multitouch info");
|
||||
tcase_add_test(tc, test_no_slots);
|
||||
tcase_add_test(tc, test_slot_number);
|
||||
tcase_add_test(tc, test_slot_init_value);
|
||||
tcase_add_test(tc, test_invalid_mt_device);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_no_slots);
|
||||
add_test(s, test_slot_number);
|
||||
add_test(s, test_slot_init_value);
|
||||
add_test(s, test_invalid_mt_device);
|
||||
|
||||
tc = tcase_create("device info");
|
||||
tcase_add_test(tc, test_device_name);
|
||||
tcase_add_test(tc, test_device_set_name);
|
||||
tcase_add_test(tc, test_device_set_ids);
|
||||
tcase_add_test(tc, test_device_get_abs_info);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_device_name);
|
||||
add_test(s, test_device_set_name);
|
||||
add_test(s, test_device_set_ids);
|
||||
add_test(s, test_device_get_abs_info);
|
||||
|
||||
tc = tcase_create("device bit manipulation");
|
||||
tcase_add_test(tc, test_device_set_abs);
|
||||
tcase_add_test(tc, test_device_enable_bit);
|
||||
tcase_add_test(tc, test_device_enable_bit_invalid);
|
||||
tcase_add_test(tc, test_device_disable_bit);
|
||||
tcase_add_test(tc, test_device_disable_bit_invalid);
|
||||
tcase_add_test(tc, test_device_kernel_change_axis);
|
||||
tcase_add_test(tc, test_device_kernel_change_axis_invalid);
|
||||
tcase_add_test(tc, test_device_kernel_set_abs_invalid_fd);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_device_set_abs);
|
||||
add_test(s, test_device_enable_bit);
|
||||
add_test(s, test_device_enable_bit_invalid);
|
||||
add_test(s, test_device_disable_bit);
|
||||
add_test(s, test_device_disable_bit_invalid);
|
||||
add_test(s, test_device_kernel_change_axis);
|
||||
add_test(s, test_device_kernel_change_axis_invalid);
|
||||
add_test(s, test_device_kernel_set_abs_invalid_fd);
|
||||
|
||||
tc = tcase_create("led manipulation");
|
||||
tcase_add_test(tc, test_led_valid);
|
||||
tcase_add_test(tc, test_led_invalid);
|
||||
tcase_add_test(tc, test_led_same);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_led_valid);
|
||||
add_test(s, test_led_invalid);
|
||||
add_test(s, test_led_same);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* 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 <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -468,10 +451,98 @@ START_TEST(test_device_grab_invalid_fd)
|
|||
}
|
||||
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)
|
||||
{
|
||||
struct uinput_device* uidev;
|
||||
struct libevdev *dev;
|
||||
int clockid;
|
||||
int rc;
|
||||
|
||||
test_create_device(&uidev, &dev,
|
||||
|
|
@ -490,7 +561,13 @@ START_TEST(test_set_clock_id)
|
|||
rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
|
||||
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);
|
||||
|
||||
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.value, ev2.value);
|
||||
|
||||
t1 = ev1.time.tv_sec * 1000000LL + ev1.time.tv_usec;
|
||||
t2 = ev2.time.tv_sec * 1000000LL + ev2.time.tv_usec;
|
||||
t1 = ev1.input_event_sec * 1000000LL + ev1.input_event_usec;
|
||||
t2 = ev2.input_event_sec * 1000000LL + ev2.input_event_usec;
|
||||
ck_assert_int_ne(t1, t2);
|
||||
|
||||
ck_assert_int_ge(ev1.time.tv_sec, t1_real.tv_sec);
|
||||
ck_assert_int_ge(ev1.time.tv_usec, t1_real.tv_nsec/1000);
|
||||
ck_assert_int_le(ev1.time.tv_sec, t2_real.tv_sec);
|
||||
ck_assert_int_le(ev1.time.tv_usec, t2_real.tv_nsec/1000);
|
||||
ck_assert_int_ge(ev1.input_event_sec, t1_real.tv_sec);
|
||||
ck_assert_int_ge(ev1.input_event_usec, t1_real.tv_nsec/1000);
|
||||
ck_assert_int_le(ev1.input_event_sec, t2_real.tv_sec);
|
||||
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.time.tv_usec, t1_mono.tv_nsec/1000);
|
||||
ck_assert_int_le(ev2.time.tv_sec, t2_mono.tv_sec);
|
||||
ck_assert_int_le(ev2.time.tv_usec, t2_mono.tv_nsec/1000);
|
||||
ck_assert_int_ge(ev2.input_event_sec, t1_mono.tv_sec);
|
||||
ck_assert_int_ge(ev2.input_event_usec, t1_mono.tv_nsec/1000);
|
||||
ck_assert_int_le(ev2.input_event_sec, t2_mono.tv_sec);
|
||||
ck_assert_int_le(ev2.input_event_usec, t2_mono.tv_nsec/1000);
|
||||
|
||||
uinput_device_free(uidev);
|
||||
libevdev_free(dev);
|
||||
|
|
@ -596,42 +673,32 @@ START_TEST(test_clock_id_events)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
libevdev_init_test(void)
|
||||
TEST_SUITE_ROOT_PRIVILEGES(libevdev_init_test)
|
||||
{
|
||||
Suite *s = suite_create("libevdev init tests");
|
||||
|
||||
TCase *tc = tcase_create("device init");
|
||||
tcase_add_test(tc, test_new_device);
|
||||
tcase_add_test(tc, test_free_device);
|
||||
tcase_add_test(tc, test_init_from_invalid_fd);
|
||||
tcase_add_test(tc, test_init_and_change_fd);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_new_device);
|
||||
add_test(s, test_free_device);
|
||||
add_test(s, test_init_from_invalid_fd);
|
||||
add_test(s, test_init_and_change_fd);
|
||||
|
||||
tc = tcase_create("log init");
|
||||
tcase_add_test(tc, test_log_init);
|
||||
tcase_add_test(tc, test_log_priority);
|
||||
tcase_add_test(tc, test_log_set_get_priority);
|
||||
tcase_add_test(tc, test_log_default_priority);
|
||||
tcase_add_test(tc, test_log_data);
|
||||
tcase_add_test(tc, test_device_log_init);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_log_init);
|
||||
add_test(s, test_log_priority);
|
||||
add_test(s, test_log_set_get_priority);
|
||||
add_test(s, test_log_default_priority);
|
||||
add_test(s, test_log_data);
|
||||
add_test(s, test_device_log_init);
|
||||
|
||||
tc = tcase_create("device fd init");
|
||||
tcase_add_test(tc, test_device_init);
|
||||
tcase_add_test(tc, test_device_init_from_fd);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_device_init);
|
||||
add_test(s, test_device_init_from_fd);
|
||||
|
||||
tc = tcase_create("device grab");
|
||||
tcase_add_test(tc, test_device_grab);
|
||||
tcase_add_test(tc, test_device_grab_invalid_fd);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_device_grab);
|
||||
add_test(s, test_device_grab_invalid_fd);
|
||||
add_test(s, test_device_grab_change_fd);
|
||||
|
||||
tc = tcase_create("clock id");
|
||||
tcase_add_test(tc, test_set_clock_id);
|
||||
tcase_add_test(tc, test_set_clock_id_invalid_fd);
|
||||
tcase_add_test(tc, test_clock_id_events);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_set_clock_id);
|
||||
add_test(s, test_set_clock_id_invalid_fd);
|
||||
add_test(s, test_clock_id_events);
|
||||
|
||||
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.
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <libevdev/libevdev.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
|
||||
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 rc;
|
||||
int pid = fork();
|
||||
|
||||
if (pid == -1)
|
||||
|
|
@ -55,35 +40,75 @@ is_debugger_attached(void)
|
|||
ptrace(PTRACE_CONT, NULL, NULL);
|
||||
ptrace(PTRACE_DETACH, ppid, NULL, NULL);
|
||||
rc = 0;
|
||||
} else
|
||||
rc = 1;
|
||||
}
|
||||
_exit(rc);
|
||||
} else {
|
||||
waitpid(pid, &status, 0);
|
||||
rc = WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
#endif /* !__FreeBSD__ */
|
||||
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;
|
||||
|
||||
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())
|
||||
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);
|
||||
|
||||
Suite *s = libevdev_has_event_test();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_add_suite(sr, libevdev_events());
|
||||
srunner_add_suite(sr, libevdev_init_test());
|
||||
srunner_add_suite(sr, queue_suite());
|
||||
srunner_add_suite(sr, event_name_suite());
|
||||
srunner_add_suite(sr, event_code_suite());
|
||||
srunner_add_suite(sr, uinput_suite());
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
SRunner *sr = srunner_create(NULL);
|
||||
for (t = &__start_test_section; t < &__stop_test_section; t++) {
|
||||
srunner_add_suite(sr, t->setup());
|
||||
}
|
||||
|
||||
srunner_run_all(sr, CK_ENV);
|
||||
|
||||
failed = srunner_ntests_failed(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.
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -69,7 +52,7 @@ START_TEST(test_uinput_create_device)
|
|||
if (max == -1)
|
||||
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),
|
||||
libevdev_has_event_code(dev2, type, code));
|
||||
}
|
||||
|
|
@ -150,7 +133,7 @@ START_TEST(test_uinput_create_device_from_fd)
|
|||
if (max == -1)
|
||||
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),
|
||||
libevdev_has_event_code(dev2, type, code));
|
||||
}
|
||||
|
|
@ -164,6 +147,93 @@ START_TEST(test_uinput_create_device_from_fd)
|
|||
}
|
||||
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)
|
||||
{
|
||||
struct libevdev *dev;
|
||||
|
|
@ -269,6 +339,8 @@ START_TEST(test_uinput_check_syspath_name)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
#endif /* __FreeBSD __ */
|
||||
|
||||
START_TEST(test_uinput_events)
|
||||
{
|
||||
struct libevdev *dev;
|
||||
|
|
@ -368,26 +440,24 @@ START_TEST(test_uinput_properties)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
uinput_suite(void)
|
||||
TEST_SUITE_ROOT_PRIVILEGES(uinput_suite)
|
||||
{
|
||||
Suite *s = suite_create("libevdev uinput device tests");
|
||||
|
||||
TCase *tc = tcase_create("device creation");
|
||||
tcase_add_test(tc, test_uinput_create_device);
|
||||
tcase_add_test(tc, test_uinput_create_device_invalid);
|
||||
tcase_add_test(tc, test_uinput_create_device_from_fd);
|
||||
tcase_add_test(tc, test_uinput_check_syspath_time);
|
||||
tcase_add_test(tc, test_uinput_check_syspath_name);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_uinput_create_device);
|
||||
add_test(s, test_uinput_create_device_invalid);
|
||||
add_test(s, test_uinput_create_device_from_fd);
|
||||
#ifdef __FreeBSD__
|
||||
add_test(s, test_uinput_check_devnode_bsd);
|
||||
add_test(s, test_uinput_check_syspath_bsd);
|
||||
#else
|
||||
add_test(s, test_uinput_check_syspath_time);
|
||||
add_test(s, test_uinput_check_syspath_name);
|
||||
#endif
|
||||
|
||||
tc = tcase_create("device events");
|
||||
tcase_add_test(tc, test_uinput_events);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_uinput_events);
|
||||
|
||||
tc = tcase_create("device properties");
|
||||
tcase_add_test(tc, test_uinput_properties);
|
||||
suite_add_tcase(s, tc);
|
||||
add_test(s, test_uinput_properties);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,3 +18,10 @@
|
|||
fun:ioctl
|
||||
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 = \
|
||||
touchpad-edge-detector \
|
||||
mouse-dpi-tool \
|
||||
|
|
@ -10,6 +10,9 @@ libevdev_ldadd = $(top_builddir)/libevdev/libevdev.la
|
|||
libevdev_events_SOURCES = libevdev-events.c
|
||||
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_LDADD = $(libevdev_ldadd)
|
||||
|
||||
|
|
@ -18,4 +21,9 @@ mouse_dpi_tool_LDADD = $(libevdev_ldadd)
|
|||
|
||||
libevdev_tweak_device_SOURCES = libevdev-tweak-device.c
|
||||
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.
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "libevdev/libevdev.h"
|
||||
|
||||
static void
|
||||
print_abs_bits(struct libevdev *dev, int axis)
|
||||
|
|
@ -112,13 +95,13 @@ print_event(struct input_event *ev)
|
|||
{
|
||||
if (ev->type == EV_SYN)
|
||||
printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
|
||||
ev->time.tv_sec,
|
||||
ev->time.tv_usec,
|
||||
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->time.tv_sec,
|
||||
ev->time.tv_usec,
|
||||
ev->input_event_sec,
|
||||
ev->input_event_usec,
|
||||
ev->type,
|
||||
libevdev_event_type_get_name(ev->type),
|
||||
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.
|
||||
*
|
||||
* 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 <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libevdev.h"
|
||||
#include "libevdev/libevdev.h"
|
||||
|
||||
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"
|
||||
"\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"
|
||||
"%s --led <led> --on|--off /dev/input/eventXYZ\n"
|
||||
"\tEnable or disable the named LED\n",
|
||||
program_invocation_short_name,
|
||||
program_invocation_short_name,
|
||||
program_invocation_short_name);
|
||||
progname,
|
||||
progname,
|
||||
progname);
|
||||
}
|
||||
|
||||
enum mode {
|
||||
|
|
@ -416,7 +399,7 @@ main(int argc, char **argv)
|
|||
rc = EXIT_SUCCESS;
|
||||
/* fallthrough */
|
||||
case MODE_NONE:
|
||||
usage();
|
||||
usage(basename(argv[0]));
|
||||
goto out;
|
||||
case MODE_ABS:
|
||||
rc = parse_options_abs(argc, argv, &changes, &axis,
|
||||
|
|
@ -440,7 +423,7 @@ main(int argc, char **argv)
|
|||
|
||||
if (optind >= argc) {
|
||||
rc = EXIT_FAILURE;
|
||||
usage();
|
||||
usage(basename(argv[0]));
|
||||
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.
|
||||
*
|
||||
* 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"
|
||||
#endif
|
||||
|
||||
#include <libevdev/libevdev.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libevdev/libevdev.h"
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static int signalled = 0;
|
||||
|
||||
struct measurements {
|
||||
int distance;
|
||||
double frequency;
|
||||
double max_frequency;
|
||||
double *frequencies;
|
||||
size_t frequencies_sz;
|
||||
size_t nfrequencies;
|
||||
uint64_t us;
|
||||
};
|
||||
|
||||
static int
|
||||
usage(void) {
|
||||
printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
|
||||
usage(const char *progname) {
|
||||
printf("Usage: %s /dev/input/event0\n", progname);
|
||||
printf("\n");
|
||||
printf("This tool reads relative events from the kernel and calculates\n"
|
||||
"the distance covered and maximum frequency of the incoming events.\n"
|
||||
|
|
@ -58,18 +44,27 @@ usage(void) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
tv2us(const struct timeval *tv)
|
||||
{
|
||||
return tv->tv_sec * 1000000 + tv->tv_usec;
|
||||
}
|
||||
|
||||
static inline double
|
||||
get_frequency(double last, double current)
|
||||
get_frequency(uint64_t last, uint64_t current)
|
||||
{
|
||||
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
|
||||
print_current_values(const struct measurements *m)
|
||||
{
|
||||
|
|
@ -89,7 +84,7 @@ print_current_values(const struct measurements *m)
|
|||
progress = (progress + 1) % 4;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -101,20 +96,23 @@ handle_event(struct measurements *m, const struct input_event *ev)
|
|||
const int idle_reset = 3000000; /* 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 */
|
||||
if (last_us + idle_reset < m->us) {
|
||||
m->frequency = 0.0;
|
||||
m->max_frequency = 0.0;
|
||||
m->distance = 0;
|
||||
} else {
|
||||
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 0;
|
||||
} else if (ev->type != EV_REL)
|
||||
}
|
||||
|
||||
if (ev->type != EV_REL)
|
||||
return 0;
|
||||
|
||||
switch(ev->code) {
|
||||
|
|
@ -126,26 +124,26 @@ handle_event(struct measurements *m, const struct input_event *ev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
signal_handler(__attribute__((__unused__)) int signal)
|
||||
{
|
||||
signalled++;
|
||||
}
|
||||
|
||||
static int
|
||||
mainloop(struct libevdev *dev, struct measurements *m) {
|
||||
struct pollfd fds[2];
|
||||
sigset_t mask;
|
||||
struct pollfd fds;
|
||||
|
||||
fds[0].fd = libevdev_get_fd(dev);
|
||||
fds[0].events = POLLIN;
|
||||
fds.fd = libevdev_get_fd(dev);
|
||||
fds.events = POLLIN;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
||||
fds[1].events = POLLIN;
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
while (poll(fds, 2, -1)) {
|
||||
while (poll(&fds, 1, -1)) {
|
||||
struct input_event ev;
|
||||
int rc;
|
||||
|
||||
if (fds[1].revents)
|
||||
if (signalled)
|
||||
break;
|
||||
|
||||
do {
|
||||
|
|
@ -153,39 +151,28 @@ mainloop(struct libevdev *dev, struct measurements *m) {
|
|||
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||
fprintf(stderr, "Error: cannot keep up\n");
|
||||
return 1;
|
||||
} else if (rc != -EAGAIN && rc < 0) {
|
||||
}
|
||||
|
||||
if (rc != -EAGAIN && rc < 0) {
|
||||
fprintf(stderr, "Error: %s\n", strerror(-rc));
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
print_summary(struct measurements *m)
|
||||
static inline double
|
||||
mean_frequency(struct measurements *m)
|
||||
{
|
||||
int res;
|
||||
int idx;
|
||||
|
||||
printf("Estimated sampling frequency: %dHz\n", (int)m->frequency);
|
||||
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);
|
||||
idx = m->nfrequencies/2;
|
||||
return m->frequencies[idx];
|
||||
}
|
||||
|
||||
static inline const char*
|
||||
|
|
@ -206,20 +193,68 @@ bustype(int bustype)
|
|||
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
|
||||
main (int argc, char **argv) {
|
||||
int rc;
|
||||
int fd;
|
||||
const char *path;
|
||||
struct libevdev *dev;
|
||||
struct measurements measurements = {0, 0, 0};
|
||||
struct measurements measurements = {0};
|
||||
|
||||
if (argc < 2)
|
||||
return usage();
|
||||
return usage(basename(argv[0]));
|
||||
|
||||
path = argv[1];
|
||||
if (path[0] == '-')
|
||||
return usage();
|
||||
return usage(basename(argv[0]));
|
||||
|
||||
fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
|
|
@ -249,17 +284,7 @@ main (int argc, char **argv) {
|
|||
|
||||
printf("\n");
|
||||
|
||||
print_summary(&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);
|
||||
print_summary(dev, &measurements);
|
||||
|
||||
libevdev_free(dev);
|
||||
close(fd);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,37 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
make
|
||||
rsync --delete -avz doc/html/ freedesktop.org:/srv/www.freedesktop.org/www/software/libevdev/doc/latest
|
||||
tag="$1"
|
||||
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.
|
||||
*
|
||||
* 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"
|
||||
#endif
|
||||
|
||||
#include <libevdev/libevdev.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libevdev/libevdev.h"
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static int signalled = 0;
|
||||
|
||||
static int
|
||||
usage(void) {
|
||||
printf("Usage: %s /dev/input/event0\n", program_invocation_short_name);
|
||||
usage(const char *progname) {
|
||||
printf("Usage: %s 12x34 /dev/input/eventX\n", progname);
|
||||
printf("\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;
|
||||
}
|
||||
|
||||
|
|
@ -54,6 +39,10 @@ struct dimensions {
|
|||
int top, bottom, left, right;
|
||||
};
|
||||
|
||||
struct size {
|
||||
int w, h;
|
||||
};
|
||||
|
||||
static int
|
||||
print_current_values(const struct dimensions *d)
|
||||
{
|
||||
|
|
@ -76,9 +65,10 @@ print_current_values(const struct dimensions *d)
|
|||
|
||||
static int
|
||||
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);
|
||||
} else if (ev->type != EV_ABS)
|
||||
|
||||
if (ev->type != EV_ABS)
|
||||
return 0;
|
||||
|
||||
switch(ev->code) {
|
||||
|
|
@ -97,26 +87,26 @@ handle_event(struct dimensions *d, const struct input_event *ev) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
signal_handler(__attribute__((__unused__)) int signal)
|
||||
{
|
||||
signalled++;
|
||||
}
|
||||
|
||||
static int
|
||||
mainloop(struct libevdev *dev, struct dimensions *dim) {
|
||||
struct pollfd fds[2];
|
||||
sigset_t mask;
|
||||
struct pollfd fds;
|
||||
|
||||
fds[0].fd = libevdev_get_fd(dev);
|
||||
fds[0].events = POLLIN;
|
||||
fds.fd = libevdev_get_fd(dev);
|
||||
fds.events = POLLIN;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
||||
fds[1].events = POLLIN;
|
||||
signal(SIGINT, signal_handler);
|
||||
|
||||
sigprocmask(SIG_BLOCK, &mask, NULL);
|
||||
|
||||
while (poll(fds, 2, -1)) {
|
||||
while (poll(&fds, 1, -1)) {
|
||||
struct input_event ev;
|
||||
int rc;
|
||||
|
||||
if (fds[1].revents)
|
||||
if (signalled)
|
||||
break;
|
||||
|
||||
do {
|
||||
|
|
@ -124,12 +114,16 @@ mainloop(struct libevdev *dev, struct dimensions *dim) {
|
|||
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||
fprintf(stderr, "Error: cannot keep up\n");
|
||||
return 1;
|
||||
} else if (rc != -EAGAIN && rc < 0) {
|
||||
}
|
||||
|
||||
if (rc != -EAGAIN && rc < 0) {
|
||||
fprintf(stderr, "Error: %s\n", strerror(-rc));
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -163,31 +157,35 @@ dmi_matchstr(struct libevdev *dev, char *match, size_t sz)
|
|||
|
||||
modalias[strlen(modalias) - 1] = '\0'; /* drop \n */
|
||||
snprintf(match, sz, "name:%s:%s", libevdev_get_name(dev), modalias);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
char match[PATH_MAX];
|
||||
int w, h;
|
||||
int xres, yres;
|
||||
|
||||
x = libevdev_get_abs_info(dev, ABS_X);
|
||||
y = libevdev_get_abs_info(dev, ABS_Y);
|
||||
w = x->maximum - x->minimum;
|
||||
h = y->maximum - y->minimum;
|
||||
w = dim->right - dim->left;
|
||||
h = dim->bottom - dim->top;
|
||||
xres = round((double)w/size->w);
|
||||
yres = round((double)h/size->h);
|
||||
|
||||
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",
|
||||
w/x->resolution, h/y->resolution);
|
||||
width/x->resolution, height/y->resolution);
|
||||
} else {
|
||||
printf("Touchpad has no resolution, size unknown\n");
|
||||
}
|
||||
|
||||
printf("Calculate resolution as:\n");
|
||||
printf(" x axis: %d/<width in mm>\n", w);
|
||||
printf(" y axis: %d/<height in mm>\n", h);
|
||||
printf("User-specified touchpad size: %dx%dmm\n", size->w, size->h);
|
||||
printf("Calculated ranges: %d/%d\n", w, h);
|
||||
printf("\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"
|
||||
"evdev:%s*\n"
|
||||
" EVDEV_ABS_00=%d:%d:<x resolution>\n"
|
||||
" EVDEV_ABS_01=%d:%d:<y resolution>\n",
|
||||
" EVDEV_ABS_00=%d:%d:%d\n"
|
||||
" EVDEV_ABS_01=%d:%d:%d\n",
|
||||
match,
|
||||
dim->left, dim->right,
|
||||
dim->top, dim->bottom);
|
||||
dim->left, dim->right, xres,
|
||||
dim->top, dim->bottom, yres);
|
||||
if (libevdev_has_event_code(dev, EV_ABS, ABS_MT_POSITION_X))
|
||||
printf(" EVDEV_ABS_35=%d:%d:<x resolution>\n"
|
||||
" EVDEV_ABS_36=%d:%d:<y resolution>\n",
|
||||
dim->left, dim->right,
|
||||
dim->top, dim->bottom);
|
||||
printf(" EVDEV_ABS_35=%d:%d:%d\n"
|
||||
" EVDEV_ABS_36=%d:%d:%d\n",
|
||||
dim->left, dim->right, xres,
|
||||
dim->top, dim->bottom, yres);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
|
|
@ -221,13 +219,26 @@ int main (int argc, char **argv) {
|
|||
const char *path;
|
||||
struct libevdev *dev;
|
||||
struct dimensions dim;
|
||||
struct size size;
|
||||
|
||||
if (argc < 2)
|
||||
return usage();
|
||||
if (argc < 3)
|
||||
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] == '-')
|
||||
return usage();
|
||||
return usage(basename(argv[0]));
|
||||
|
||||
fd = open(path, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
|
|
@ -273,7 +284,7 @@ int main (int argc, char **argv) {
|
|||
rc = mainloop(dev, &dim);
|
||||
printf("\n\n");
|
||||
|
||||
print_udev_override_rule(dev, &dim);
|
||||
print_udev_override_rule(dev, &dim, &size);
|
||||
|
||||
out:
|
||||
libevdev_free(dev);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue