evdev-binary 1.9.3__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- evdev/__init__.py +39 -0
- evdev/_ecodes.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/_input.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/_uinput.cpython-314-x86_64-linux-musl.so +0 -0
- evdev/device.py +440 -0
- evdev/ecodes.py +3885 -0
- evdev/ecodes_runtime.py +111 -0
- evdev/eventio.py +152 -0
- evdev/eventio_async.py +106 -0
- evdev/events.py +192 -0
- evdev/evtest.py +181 -0
- evdev/ff.py +198 -0
- evdev/genecodes_c.py +147 -0
- evdev/genecodes_py.py +54 -0
- evdev/input.c +580 -0
- evdev/py.typed +0 -0
- evdev/uinput.c +417 -0
- evdev/uinput.py +375 -0
- evdev/util.py +146 -0
- evdev_binary-1.9.3.dist-info/METADATA +48 -0
- evdev_binary-1.9.3.dist-info/RECORD +24 -0
- evdev_binary-1.9.3.dist-info/WHEEL +5 -0
- evdev_binary-1.9.3.dist-info/licenses/LICENSE +29 -0
- evdev_binary-1.9.3.dist-info/top_level.txt +1 -0
evdev/evtest.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Usage: evtest [options] [<device>, ...]
|
|
3
|
+
|
|
4
|
+
Input device enumerator and event monitor.
|
|
5
|
+
|
|
6
|
+
Running evtest without any arguments will let you select
|
|
7
|
+
from a list of all readable input devices.
|
|
8
|
+
|
|
9
|
+
Options:
|
|
10
|
+
-h, --help Show this help message and exit.
|
|
11
|
+
-c, --capabilities List device capabilities and exit.
|
|
12
|
+
-g, --grab Other applications will not receive events from
|
|
13
|
+
the selected devices while evtest is running.
|
|
14
|
+
|
|
15
|
+
Examples:
|
|
16
|
+
evtest /dev/input/event0 /dev/input/event1
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import atexit
|
|
20
|
+
import optparse
|
|
21
|
+
import re
|
|
22
|
+
import select
|
|
23
|
+
import sys
|
|
24
|
+
import termios
|
|
25
|
+
|
|
26
|
+
from . import AbsInfo, InputDevice, ecodes, list_devices
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def parseopt():
|
|
30
|
+
parser = optparse.OptionParser(add_help_option=False)
|
|
31
|
+
parser.add_option("-h", "--help", action="store_true")
|
|
32
|
+
parser.add_option("-g", "--grab", action="store_true")
|
|
33
|
+
parser.add_option("-c", "--capabilities", action="store_true")
|
|
34
|
+
return parser.parse_args()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def main():
|
|
38
|
+
opts, devices = parseopt()
|
|
39
|
+
if opts.help:
|
|
40
|
+
print(__doc__.strip())
|
|
41
|
+
return 0
|
|
42
|
+
|
|
43
|
+
if not devices:
|
|
44
|
+
devices = select_devices()
|
|
45
|
+
else:
|
|
46
|
+
devices = [InputDevice(path) for path in devices]
|
|
47
|
+
|
|
48
|
+
if opts.capabilities:
|
|
49
|
+
for device in devices:
|
|
50
|
+
print_capabilities(device)
|
|
51
|
+
return 0
|
|
52
|
+
|
|
53
|
+
if opts.grab:
|
|
54
|
+
for device in devices:
|
|
55
|
+
device.grab()
|
|
56
|
+
|
|
57
|
+
# Disable tty echoing if stdin is a tty.
|
|
58
|
+
if sys.stdin.isatty():
|
|
59
|
+
toggle_tty_echo(sys.stdin, enable=False)
|
|
60
|
+
atexit.register(toggle_tty_echo, sys.stdin, enable=True)
|
|
61
|
+
|
|
62
|
+
print("Listening for events (press ctrl-c to exit) ...")
|
|
63
|
+
fd_to_device = {dev.fd: dev for dev in devices}
|
|
64
|
+
while True:
|
|
65
|
+
r, w, e = select.select(fd_to_device, [], [])
|
|
66
|
+
|
|
67
|
+
for fd in r:
|
|
68
|
+
for event in fd_to_device[fd].read():
|
|
69
|
+
print_event(event)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def select_devices(device_dir="/dev/input"):
|
|
73
|
+
"""
|
|
74
|
+
Select one or more devices from a list of accessible input devices.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def devicenum(device_path):
|
|
78
|
+
digits = re.findall(r"\d+$", device_path)
|
|
79
|
+
return [int(i) for i in digits]
|
|
80
|
+
|
|
81
|
+
devices = sorted(list_devices(device_dir), key=devicenum)
|
|
82
|
+
devices = [InputDevice(path) for path in devices]
|
|
83
|
+
if not devices:
|
|
84
|
+
msg = "error: no input devices found (do you have rw permission on %s/*?)"
|
|
85
|
+
print(msg % device_dir, file=sys.stderr)
|
|
86
|
+
sys.exit(1)
|
|
87
|
+
|
|
88
|
+
dev_format = "{0:<3} {1.path:<20} {1.name:<35} {1.phys:<35} {1.uniq:<4}"
|
|
89
|
+
dev_lines = [dev_format.format(num, dev) for num, dev in enumerate(devices)]
|
|
90
|
+
|
|
91
|
+
print("ID {:<20} {:<35} {:<35} {}".format("Device", "Name", "Phys", "Uniq"))
|
|
92
|
+
print("-" * len(max(dev_lines, key=len)))
|
|
93
|
+
print("\n".join(dev_lines))
|
|
94
|
+
print()
|
|
95
|
+
|
|
96
|
+
choices = input("Select devices [0-%s]: " % (len(dev_lines) - 1))
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
choices = choices.split()
|
|
100
|
+
choices = [devices[int(num)] for num in choices]
|
|
101
|
+
except ValueError:
|
|
102
|
+
choices = None
|
|
103
|
+
|
|
104
|
+
if not choices:
|
|
105
|
+
msg = "error: invalid input - please enter one or more numbers separated by spaces"
|
|
106
|
+
print(msg, file=sys.stderr)
|
|
107
|
+
sys.exit(1)
|
|
108
|
+
|
|
109
|
+
return choices
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def print_capabilities(device):
|
|
113
|
+
capabilities = device.capabilities(verbose=True)
|
|
114
|
+
input_props = device.input_props(verbose=True)
|
|
115
|
+
|
|
116
|
+
print("Device name: {.name}".format(device))
|
|
117
|
+
print("Device info: {.info}".format(device))
|
|
118
|
+
print("Repeat settings: {}\n".format(device.repeat))
|
|
119
|
+
|
|
120
|
+
if ("EV_LED", ecodes.EV_LED) in capabilities:
|
|
121
|
+
leds = ",".join(i[0] for i in device.leds(True))
|
|
122
|
+
print("Active LEDs: %s" % leds)
|
|
123
|
+
|
|
124
|
+
active_keys = ",".join(k[0] for k in device.active_keys(True))
|
|
125
|
+
print("Active keys: %s\n" % active_keys)
|
|
126
|
+
|
|
127
|
+
if input_props:
|
|
128
|
+
print("Input properties:")
|
|
129
|
+
for type, code in input_props:
|
|
130
|
+
print(" %s %s" % (type, code))
|
|
131
|
+
print()
|
|
132
|
+
|
|
133
|
+
print("Device capabilities:")
|
|
134
|
+
for type, codes in capabilities.items():
|
|
135
|
+
print(" Type {} {}:".format(*type))
|
|
136
|
+
for code in codes:
|
|
137
|
+
# code <- ('BTN_RIGHT', 273) or (['BTN_LEFT', 'BTN_MOUSE'], 272)
|
|
138
|
+
if isinstance(code[1], AbsInfo):
|
|
139
|
+
print(" Code {:<4} {}:".format(*code[0]))
|
|
140
|
+
print(" {}".format(code[1]))
|
|
141
|
+
else:
|
|
142
|
+
# Multiple names may resolve to one value.
|
|
143
|
+
s = ", ".join(code[0]) if isinstance(code[0], list) else code[0]
|
|
144
|
+
print(" Code {:<4} {}".format(s, code[1]))
|
|
145
|
+
print("")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def print_event(e):
|
|
149
|
+
if e.type == ecodes.EV_SYN:
|
|
150
|
+
if e.code == ecodes.SYN_MT_REPORT:
|
|
151
|
+
msg = "time {:<17} +++++++++++++ {} +++++++++++++"
|
|
152
|
+
elif e.code == ecodes.SYN_DROPPED:
|
|
153
|
+
msg = "time {:<17} !!!!!!!!!!!!! {} !!!!!!!!!!!!!"
|
|
154
|
+
else:
|
|
155
|
+
msg = "time {:<17} ------------- {} -------------"
|
|
156
|
+
print(msg.format(e.timestamp(), ecodes.SYN[e.code]))
|
|
157
|
+
else:
|
|
158
|
+
if e.type in ecodes.bytype:
|
|
159
|
+
codename = ecodes.bytype[e.type][e.code]
|
|
160
|
+
else:
|
|
161
|
+
codename = "?"
|
|
162
|
+
|
|
163
|
+
evfmt = "time {:<17} type {} ({}), code {:<4} ({}), value {}"
|
|
164
|
+
print(evfmt.format(e.timestamp(), e.type, ecodes.EV[e.type], e.code, codename, e.value))
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def toggle_tty_echo(fh, enable=True):
|
|
168
|
+
flags = termios.tcgetattr(fh.fileno())
|
|
169
|
+
if enable:
|
|
170
|
+
flags[3] |= termios.ECHO
|
|
171
|
+
else:
|
|
172
|
+
flags[3] &= ~termios.ECHO
|
|
173
|
+
termios.tcsetattr(fh.fileno(), termios.TCSANOW, flags)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
if __name__ == "__main__":
|
|
177
|
+
try:
|
|
178
|
+
ret = main()
|
|
179
|
+
except (KeyboardInterrupt, EOFError):
|
|
180
|
+
ret = 0
|
|
181
|
+
sys.exit(ret)
|
evdev/ff.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
|
|
3
|
+
from . import ecodes
|
|
4
|
+
|
|
5
|
+
_u8 = ctypes.c_uint8
|
|
6
|
+
_u16 = ctypes.c_uint16
|
|
7
|
+
_u32 = ctypes.c_uint32
|
|
8
|
+
_s16 = ctypes.c_int16
|
|
9
|
+
_s32 = ctypes.c_int32
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Replay(ctypes.Structure):
|
|
13
|
+
"""
|
|
14
|
+
Defines scheduling of the force-feedback effect
|
|
15
|
+
@length: duration of the effect
|
|
16
|
+
@delay: delay before effect should start playing
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
_fields_ = [
|
|
20
|
+
("length", _u16),
|
|
21
|
+
("delay", _u16),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Trigger(ctypes.Structure):
|
|
26
|
+
"""
|
|
27
|
+
Defines what triggers the force-feedback effect
|
|
28
|
+
@button: number of the button triggering the effect
|
|
29
|
+
@interval: controls how soon the effect can be re-triggered
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
_fields_ = [
|
|
33
|
+
("button", _u16),
|
|
34
|
+
("interval", _u16),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Envelope(ctypes.Structure):
|
|
39
|
+
"""
|
|
40
|
+
Generic force-feedback effect envelope
|
|
41
|
+
@attack_length: duration of the attack (ms)
|
|
42
|
+
@attack_level: level at the beginning of the attack
|
|
43
|
+
@fade_length: duration of fade (ms)
|
|
44
|
+
@fade_level: level at the end of fade
|
|
45
|
+
|
|
46
|
+
The @attack_level and @fade_level are absolute values; when applying
|
|
47
|
+
envelope force-feedback core will convert to positive/negative
|
|
48
|
+
value based on polarity of the default level of the effect.
|
|
49
|
+
Valid range for the attack and fade levels is 0x0000 - 0x7fff
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
_fields_ = [
|
|
53
|
+
("attack_length", _u16),
|
|
54
|
+
("attack_level", _u16),
|
|
55
|
+
("fade_length", _u16),
|
|
56
|
+
("fade_level", _u16),
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class Constant(ctypes.Structure):
|
|
61
|
+
"""
|
|
62
|
+
Defines parameters of a constant force-feedback effect
|
|
63
|
+
@level: strength of the effect; may be negative
|
|
64
|
+
@envelope: envelope data
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
_fields_ = [
|
|
68
|
+
("level", _s16),
|
|
69
|
+
("ff_envelope", Envelope),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Ramp(ctypes.Structure):
|
|
74
|
+
"""
|
|
75
|
+
Defines parameters of a ramp force-feedback effect
|
|
76
|
+
@start_level: beginning strength of the effect; may be negative
|
|
77
|
+
@end_level: final strength of the effect; may be negative
|
|
78
|
+
@envelope: envelope data
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
_fields_ = [
|
|
82
|
+
("start_level", _s16),
|
|
83
|
+
("end_level", _s16),
|
|
84
|
+
("ff_envelope", Envelope),
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Condition(ctypes.Structure):
|
|
89
|
+
"""
|
|
90
|
+
Defines a spring or friction force-feedback effect
|
|
91
|
+
@right_saturation: maximum level when joystick moved all way to the right
|
|
92
|
+
@left_saturation: same for the left side
|
|
93
|
+
@right_coeff: controls how fast the force grows when the joystick moves to the right
|
|
94
|
+
@left_coeff: same for the left side
|
|
95
|
+
@deadband: size of the dead zone, where no force is produced
|
|
96
|
+
@center: position of the dead zone
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
_fields_ = [
|
|
100
|
+
("right_saturation", _u16),
|
|
101
|
+
("left_saturation", _u16),
|
|
102
|
+
("right_coeff", _s16),
|
|
103
|
+
("left_coeff", _s16),
|
|
104
|
+
("deadband", _u16),
|
|
105
|
+
("center", _s16),
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class Periodic(ctypes.Structure):
|
|
110
|
+
"""
|
|
111
|
+
Defines parameters of a periodic force-feedback effect
|
|
112
|
+
@waveform: kind of the effect (wave)
|
|
113
|
+
@period: period of the wave (ms)
|
|
114
|
+
@magnitude: peak value
|
|
115
|
+
@offset: mean value of the wave (roughly)
|
|
116
|
+
@phase: 'horizontal' shift
|
|
117
|
+
@envelope: envelope data
|
|
118
|
+
@custom_len: number of samples (FF_CUSTOM only)
|
|
119
|
+
@custom_data: buffer of samples (FF_CUSTOM only)
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
_fields_ = [
|
|
123
|
+
("waveform", _u16),
|
|
124
|
+
("period", _u16),
|
|
125
|
+
("magnitude", _s16),
|
|
126
|
+
("offset", _s16),
|
|
127
|
+
("phase", _u16),
|
|
128
|
+
("envelope", Envelope),
|
|
129
|
+
("custom_len", _u32),
|
|
130
|
+
("custom_data", ctypes.POINTER(_s16)),
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class Rumble(ctypes.Structure):
|
|
135
|
+
"""
|
|
136
|
+
Defines parameters of a periodic force-feedback effect
|
|
137
|
+
@strong_magnitude: magnitude of the heavy motor
|
|
138
|
+
@weak_magnitude: magnitude of the light one
|
|
139
|
+
|
|
140
|
+
Some rumble pads have two motors of different weight. Strong_magnitude
|
|
141
|
+
represents the magnitude of the vibration generated by the heavy one.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
_fields_ = [
|
|
145
|
+
("strong_magnitude", _u16),
|
|
146
|
+
("weak_magnitude", _u16),
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class EffectType(ctypes.Union):
|
|
151
|
+
_fields_ = [
|
|
152
|
+
("ff_constant_effect", Constant),
|
|
153
|
+
("ff_ramp_effect", Ramp),
|
|
154
|
+
("ff_periodic_effect", Periodic),
|
|
155
|
+
("ff_condition_effect", Condition * 2), # one for each axis
|
|
156
|
+
("ff_rumble_effect", Rumble),
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class Effect(ctypes.Structure):
|
|
161
|
+
_fields_ = [
|
|
162
|
+
("type", _u16),
|
|
163
|
+
("id", _s16),
|
|
164
|
+
("direction", _u16),
|
|
165
|
+
("ff_trigger", Trigger),
|
|
166
|
+
("ff_replay", Replay),
|
|
167
|
+
("u", EffectType),
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class UInputUpload(ctypes.Structure):
|
|
172
|
+
_fields_ = [
|
|
173
|
+
("request_id", _u32),
|
|
174
|
+
("retval", _s32),
|
|
175
|
+
("effect", Effect),
|
|
176
|
+
("old", Effect),
|
|
177
|
+
]
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class UInputErase(ctypes.Structure):
|
|
181
|
+
_fields_ = [
|
|
182
|
+
("request_id", _u32),
|
|
183
|
+
("retval", _s32),
|
|
184
|
+
("effect_id", _u32),
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# ff_types = {
|
|
189
|
+
# ecodes.FF_CONSTANT,
|
|
190
|
+
# ecodes.FF_PERIODIC,
|
|
191
|
+
# ecodes.FF_RAMP,
|
|
192
|
+
# ecodes.FF_SPRING,
|
|
193
|
+
# ecodes.FF_FRICTION,
|
|
194
|
+
# ecodes.FF_DAMPER,
|
|
195
|
+
# ecodes.FF_RUMBLE,
|
|
196
|
+
# ecodes.FF_INERTIA,
|
|
197
|
+
# ecodes.FF_CUSTOM,
|
|
198
|
+
# }
|
evdev/genecodes_c.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generate a Python extension module with the constants defined in linux/input.h.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import getopt
|
|
6
|
+
import os
|
|
7
|
+
import re
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
# -----------------------------------------------------------------------------
|
|
11
|
+
# The default header file locations to try.
|
|
12
|
+
headers = [
|
|
13
|
+
"/usr/include/linux/input.h",
|
|
14
|
+
"/usr/include/linux/input-event-codes.h",
|
|
15
|
+
"/usr/include/linux/uinput.h",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
opts, args = getopt.getopt(sys.argv[1:], "", ["ecodes", "stubs", "reproducible"])
|
|
19
|
+
if not opts:
|
|
20
|
+
print("usage: genecodes.py [--ecodes|--stubs] [--reproducible] <headers>")
|
|
21
|
+
exit(2)
|
|
22
|
+
|
|
23
|
+
if args:
|
|
24
|
+
headers = args
|
|
25
|
+
|
|
26
|
+
reproducible = ("--reproducible", "") in opts
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# -----------------------------------------------------------------------------
|
|
30
|
+
macro_regex = r"#define\s+((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF|UI_FF|INPUT_PROP)_\w+)"
|
|
31
|
+
macro_regex = re.compile(macro_regex)
|
|
32
|
+
|
|
33
|
+
if reproducible:
|
|
34
|
+
uname = "hidden for reproducibility"
|
|
35
|
+
else:
|
|
36
|
+
# Uname without hostname.
|
|
37
|
+
uname = list(os.uname())
|
|
38
|
+
uname = " ".join((uname[0], *uname[2:]))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# -----------------------------------------------------------------------------
|
|
42
|
+
template_ecodes = r"""
|
|
43
|
+
#include <Python.h>
|
|
44
|
+
#ifdef __FreeBSD__
|
|
45
|
+
#include <dev/evdev/input.h>
|
|
46
|
+
#include <dev/evdev/uinput.h>
|
|
47
|
+
#else
|
|
48
|
+
#include <linux/input.h>
|
|
49
|
+
#include <linux/uinput.h>
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
/* Automatically generated by evdev.genecodes */
|
|
53
|
+
/* Generated on %s */
|
|
54
|
+
/* Generated from %s */
|
|
55
|
+
|
|
56
|
+
#define MODULE_NAME "_ecodes"
|
|
57
|
+
#define MODULE_HELP "linux/input.h macros"
|
|
58
|
+
|
|
59
|
+
static PyMethodDef MethodTable[] = {
|
|
60
|
+
{ NULL, NULL, 0, NULL}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
static struct PyModuleDef moduledef = {
|
|
64
|
+
PyModuleDef_HEAD_INIT,
|
|
65
|
+
MODULE_NAME,
|
|
66
|
+
MODULE_HELP,
|
|
67
|
+
-1, /* m_size */
|
|
68
|
+
MethodTable, /* m_methods */
|
|
69
|
+
NULL, /* m_reload */
|
|
70
|
+
NULL, /* m_traverse */
|
|
71
|
+
NULL, /* m_clear */
|
|
72
|
+
NULL, /* m_free */
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
PyMODINIT_FUNC
|
|
76
|
+
PyInit__ecodes(void)
|
|
77
|
+
{
|
|
78
|
+
PyObject* m = PyModule_Create(&moduledef);
|
|
79
|
+
if (m == NULL) return NULL;
|
|
80
|
+
|
|
81
|
+
%s
|
|
82
|
+
|
|
83
|
+
return m;
|
|
84
|
+
}
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
template_stubs = r"""
|
|
89
|
+
# Automatically generated by evdev.genecodes
|
|
90
|
+
# Generated on %s
|
|
91
|
+
# Generated from %s
|
|
92
|
+
|
|
93
|
+
# pylint: skip-file
|
|
94
|
+
|
|
95
|
+
ecodes: dict[str, int]
|
|
96
|
+
keys: dict[int, str|list[str]]
|
|
97
|
+
bytype: dict[int, dict[int, str|list[str]]]
|
|
98
|
+
|
|
99
|
+
KEY: dict[int, str|list[str]]
|
|
100
|
+
ABS: dict[int, str|list[str]]
|
|
101
|
+
REL: dict[int, str|list[str]]
|
|
102
|
+
SW: dict[int, str|list[str]]
|
|
103
|
+
MSC: dict[int, str|list[str]]
|
|
104
|
+
LED: dict[int, str|list[str]]
|
|
105
|
+
BTN: dict[int, str|list[str]]
|
|
106
|
+
REP: dict[int, str|list[str]]
|
|
107
|
+
SND: dict[int, str|list[str]]
|
|
108
|
+
ID: dict[int, str|list[str]]
|
|
109
|
+
EV: dict[int, str|list[str]]
|
|
110
|
+
BUS: dict[int, str|list[str]]
|
|
111
|
+
SYN: dict[int, str|list[str]]
|
|
112
|
+
FF_STATUS: dict[int, str|list[str]]
|
|
113
|
+
FF_INPUT_PROP: dict[int, str|list[str]]
|
|
114
|
+
|
|
115
|
+
%s
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def parse_headers(headers=headers):
|
|
120
|
+
for header in headers:
|
|
121
|
+
try:
|
|
122
|
+
fh = open(header)
|
|
123
|
+
except (IOError, OSError):
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
for line in fh:
|
|
127
|
+
macro = macro_regex.search(line)
|
|
128
|
+
if macro:
|
|
129
|
+
yield macro.group(1)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
all_macros = list(parse_headers())
|
|
133
|
+
if not all_macros:
|
|
134
|
+
print("no input macros found in: %s" % " ".join(headers), file=sys.stderr)
|
|
135
|
+
sys.exit(1)
|
|
136
|
+
|
|
137
|
+
# pylint: disable=possibly-used-before-assignment, used-before-assignment
|
|
138
|
+
if ("--ecodes", "") in opts:
|
|
139
|
+
body = (" PyModule_AddIntMacro(m, %s);" % macro for macro in all_macros)
|
|
140
|
+
template = template_ecodes
|
|
141
|
+
elif ("--stubs", "") in opts:
|
|
142
|
+
body = ("%s: int" % macro for macro in all_macros)
|
|
143
|
+
template = template_stubs
|
|
144
|
+
|
|
145
|
+
body = os.linesep.join(body)
|
|
146
|
+
text = template % (uname, headers if not reproducible else ["hidden for reproducibility"], body)
|
|
147
|
+
print(text.strip())
|
evdev/genecodes_py.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from unittest import mock
|
|
3
|
+
from pprint import PrettyPrinter
|
|
4
|
+
|
|
5
|
+
sys.modules["evdev.ecodes"] = mock.Mock()
|
|
6
|
+
from evdev import ecodes_runtime as ecodes
|
|
7
|
+
|
|
8
|
+
pprint = PrettyPrinter(indent=2, sort_dicts=True, width=120).pprint
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
print("# Automatically generated by evdev.genecodes_py")
|
|
12
|
+
print()
|
|
13
|
+
print('"""')
|
|
14
|
+
print(ecodes.__doc__.strip())
|
|
15
|
+
print('"""')
|
|
16
|
+
|
|
17
|
+
print()
|
|
18
|
+
print("from typing import Final, Dict, Tuple, Union")
|
|
19
|
+
print()
|
|
20
|
+
|
|
21
|
+
for name, value in ecodes.ecodes.items():
|
|
22
|
+
print(f"{name}: Final[int] = {value}")
|
|
23
|
+
print()
|
|
24
|
+
|
|
25
|
+
entries = [
|
|
26
|
+
("ecodes", "Dict[str, int]", "#: Mapping of names to values."),
|
|
27
|
+
("bytype", "Dict[int, Dict[int, Union[str, Tuple[str]]]]", "#: Mapping of event types to other value/name mappings."),
|
|
28
|
+
("keys", "Dict[int, Union[str, Tuple[str]]]", "#: Keys are a combination of all BTN and KEY codes."),
|
|
29
|
+
("KEY", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
30
|
+
("ABS", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
31
|
+
("REL", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
32
|
+
("SW", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
33
|
+
("MSC", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
34
|
+
("LED", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
35
|
+
("BTN", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
36
|
+
("REP", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
37
|
+
("SND", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
38
|
+
("ID", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
39
|
+
("EV", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
40
|
+
("BUS", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
41
|
+
("SYN", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
42
|
+
("FF", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
43
|
+
("UI_FF", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
44
|
+
("FF_STATUS", "Dict[int, Union[str, Tuple[str]]]", None),
|
|
45
|
+
("INPUT_PROP", "Dict[int, Union[str, Tuple[str]]]", None)
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
for key, annotation, doc in entries:
|
|
49
|
+
if doc:
|
|
50
|
+
print(doc)
|
|
51
|
+
|
|
52
|
+
print(f"{key}: {annotation} = ", end="")
|
|
53
|
+
pprint(getattr(ecodes, key))
|
|
54
|
+
print()
|