Skip to content

Commit be896dc

Browse files
committed
Test setup script
1 parent 3c92d85 commit be896dc

File tree

3 files changed

+133
-95
lines changed

3 files changed

+133
-95
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,9 @@ jobs:
2424
sudo apt-get install -y linux-image-$(uname -r) linux-modules-extra-$(uname -r)
2525
- name: Setup user groups
2626
run: |
27-
echo KERNEL==\"uinput\", SUBSYSTEM==\"misc\" GROUP=\"docker\", MODE=\"0666\" | sudo tee /etc/udev/rules.d/99-$USER.rules
28-
echo KERNEL==\"event[0-9]*\", SUBSYSTEM==\"input\" GROUP=\"docker\", MODE=\"0666\" | sudo tee -a /etc/udev/rules.d/99-$USER.rules
29-
echo SUBSYSTEM==\"video4linux\" GROUP=\"docker\", MODE=\"0666\" | sudo tee -a /etc/udev/rules.d/99-$USER.rules
30-
echo KERNEL==\"gpiochip[0-9]*\", SUBSYSTEM==\"gpio\", GROUP=\"docker\", MODE=\"0666\" | sudo tee -a /etc/udev/rules.d/99-$USER.rules
31-
sudo udevadm control --reload-rules
32-
sudo udevadm trigger
33-
sudo modprobe -a uinput
34-
sudo modprobe vivid n_devs=1 node_types=0xe1d3d vid_cap_nr=190 vid_out_nr=191 meta_cap_nr=192 meta_out_nr=193
35-
sudo modprobe gpio-sim
36-
sudo modprobe gpio-aggregator
37-
sudo python scripts/setup-gpio-sim.py
27+
sudo python scripts/test_setup.py
3828
ls -lsa /dev/video* /dev/uinput /dev/gpio* /dev/inp*
3929
40-
4130
- name: Set up Python ${{ matrix.python-version }}
4231
id: setuppy
4332
uses: actions/setup-python@v5

scripts/setup-gpio-sim.py

Lines changed: 0 additions & 83 deletions
This file was deleted.

scripts/test_setup.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
from pathlib import Path
2+
from subprocess import run
3+
from sys import argv
4+
5+
user_group = None if len(argv) < 2 else argv[1]
6+
input_group = user_group or "input"
7+
video_group = user_group or "video"
8+
9+
RULES = f"""\
10+
KERNEL=="uinput", SUBSYSTEM=="misc" GROUP="{input_group}", MODE="0666"
11+
KERNEL=="event[0-9]*", SUBSYSTEM=="input" GROUP="{input_group}", MODE="0666"
12+
13+
KERNEL=="uleds", GROUP="input", MODE="0664"
14+
SUBSYSTEM=="leds", ACTION=="add", RUN+="/bin/chmod -R g=u,o=u /sys%p"
15+
SUBSYSTEM=="leds", ACTION=="change", ENV{{TRIGGER}}!="none", RUN+="/bin/chmod -R g=u,o=u /sys%p"
16+
17+
SUBSYSTEM=="video4linux" GROUP="{video_group}", MODE="0666"
18+
19+
KERNEL=="gpiochip[0-9]*", SUBSYSTEM=="gpio", GROUP="{input_group}", MODE="0666"
20+
"""
21+
22+
MODULES = {
23+
"uinput": "",
24+
"uleds": "",
25+
"gpio-sim": "",
26+
"vivid": "n_devs=1 node_types=0xe1d3d vid_cap_nr=190 vid_out_nr=191 meta_cap_nr=192 meta_out_nr=193",
27+
}
28+
29+
30+
def loaded_modules():
31+
return {line.split()[0] for line in Path("/proc/modules").read_text().splitlines()}
32+
33+
34+
LOADED_MODULES = loaded_modules()
35+
36+
37+
def handle_rules():
38+
print("Checking rules")
39+
rules = Path("/etc/udev/rules.d/99-linuxpy.rules")
40+
if rules.exists() and RULES in rules.read_text():
41+
print(" Already prepared")
42+
else:
43+
print(f" Writing rules {rules}")
44+
rules.write_text(RULES)
45+
print(" Reloading rules")
46+
run("udevadm control --reload-rules".split())
47+
run("udevadm trigger".split())
48+
49+
50+
def handle_module(mod_name):
51+
print(f"Handling {mod_name}")
52+
if mod_name in LOADED_MODULES:
53+
print(f" Unloading {mod_name}")
54+
run(f"modprobe -r {mod_name}".split())
55+
args = MODULES[mod_name]
56+
print(f" Loading {mod_name}")
57+
run(f"modprobe {mod_name} {args}".split())
58+
59+
60+
def handle_gpio_sim():
61+
print("Preparing GPIO sim")
62+
mounts = Path("/proc/mounts")
63+
for dtype, mpath, fstype, *_ in mounts.read_text().splitlines():
64+
if dtype == "configfs" and fstype == "configfs":
65+
CONFIGFS_PATH = Path(mpath)
66+
else:
67+
CONFIGFS_PATH = Path("/sys/kernel/config/gpio-sim")
68+
69+
def Line(name, direction=None):
70+
result = {"name": name}
71+
if direction:
72+
result["hog"] = {"name": f"{name}-hog", "direction": direction}
73+
return result
74+
75+
cfg = {
76+
"name": "chip99",
77+
"banks": [
78+
{
79+
"lines": [
80+
Line("L-I0"),
81+
Line("L-I1"),
82+
Line("L-I2", "input"),
83+
Line("L-O0", "output-high"),
84+
Line("L-O1", "output-low"),
85+
Line("L-O2"),
86+
]
87+
},
88+
],
89+
}
90+
91+
def mkdir(path):
92+
print(f" Creating {path}")
93+
path.mkdir()
94+
95+
path = CONFIGFS_PATH / cfg["name"]
96+
live = path / "live"
97+
98+
# clean up first
99+
if path.exists():
100+
live.write_text("0")
101+
for directory, _, _ in path.walk(top_down=False):
102+
directory.rmdir()
103+
104+
mkdir(path)
105+
for bank_id, bank in enumerate(cfg["banks"]):
106+
lines = bank["lines"]
107+
108+
bpath = path / f"gpio-bank{bank_id}"
109+
mkdir(bpath)
110+
blabel = bank.get("name", f"gpio-sim-bank{bank_id}")
111+
112+
(bpath / "num_lines").write_text("16")
113+
(bpath / "label").write_text(blabel)
114+
for line_id, line in enumerate(lines):
115+
lpath = bpath / f"line{line_id}"
116+
mkdir(lpath)
117+
(lpath / "name").write_text(line.get("name", f"L-{line_id}"))
118+
if hog := line.get("hog"):
119+
hpath = lpath / "hog"
120+
mkdir(hpath)
121+
(hpath / "name").write_text(hog["name"])
122+
(hpath / "direction").write_text(hog["direction"])
123+
124+
live.write_text("1")
125+
126+
127+
handle_rules()
128+
129+
for mod_name in MODULES:
130+
handle_module(mod_name)
131+
132+
handle_gpio_sim()

0 commit comments

Comments
 (0)