fix(server): map eye links from distinct capture nodes
This commit is contained in:
parent
76a6df4f60
commit
97abb938c5
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1642,7 +1642,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||
|
||||
[[package]]
|
||||
name = "lesavka_client"
|
||||
version = "0.13.15"
|
||||
version = "0.13.16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-stream",
|
||||
@ -1676,7 +1676,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lesavka_common"
|
||||
version = "0.13.15"
|
||||
version = "0.13.16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
@ -1688,7 +1688,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lesavka_server"
|
||||
version = "0.13.15"
|
||||
version = "0.13.16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
|
||||
@ -4,7 +4,7 @@ path = "src/main.rs"
|
||||
|
||||
[package]
|
||||
name = "lesavka_client"
|
||||
version = "0.13.15"
|
||||
version = "0.13.16"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "lesavka_common"
|
||||
version = "0.13.15"
|
||||
version = "0.13.16"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@ -320,49 +320,43 @@ if systemctl list-unit-files | grep -q '^relay.service'; then
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
# probe v4l2 devices for GC311s (07ca:3311)
|
||||
mapfile -t GC_VIDEOS < <(
|
||||
sudo v4l2-ctl --list-devices 2>/dev/null |
|
||||
awk '/Live Gamer MINI/{getline; print $1}'
|
||||
mapfile -t GC_CAPTURE_PAIRS < <(
|
||||
for dev in /dev/video*; do
|
||||
props=$(sudo udevadm info -q property -n "$dev" 2>/dev/null || true)
|
||||
index=$(cat "/sys/class/video4linux/$(basename "$dev")/index" 2>/dev/null || true)
|
||||
if echo "$props" | grep -q 'ID_VENDOR_ID=07ca' \
|
||||
&& echo "$props" | grep -q 'ID_MODEL_ID=3311' \
|
||||
&& [ "$index" = "0" ]; then
|
||||
tag=$(printf '%s\n' "$props" | awk -F= '/^ID_PATH_TAG=/{print $2}')
|
||||
if [ -n "$tag" ]; then
|
||||
printf '%s %s\n' "$tag" "$dev"
|
||||
fi
|
||||
fi
|
||||
done | sort -u
|
||||
)
|
||||
|
||||
# fallback via udev if v4l2-ctl output is empty/partial
|
||||
if [ "${#GC_VIDEOS[@]}" -ne 2 ]; then
|
||||
mapfile -t GC_VIDEOS < <(
|
||||
for dev in /dev/video*; do
|
||||
props=$(sudo udevadm info -q property -n "$dev" 2>/dev/null || true)
|
||||
if echo "$props" | grep -q 'ID_VENDOR_ID=07ca' && echo "$props" | grep -q 'ID_MODEL_ID=3311'; then
|
||||
echo "$dev"
|
||||
fi
|
||||
done | sort -u
|
||||
)
|
||||
fi
|
||||
|
||||
if [ "${#GC_VIDEOS[@]}" -ne 2 ]; then
|
||||
if [ "${#GC_CAPTURE_PAIRS[@]}" -ne 2 ]; then
|
||||
echo "⚠️ GC311 capture cards not fully present; skipping udev eye-link refresh." >&2
|
||||
if [ "${#GC_VIDEOS[@]}" -eq 0 ]; then
|
||||
if [ "${#GC_CAPTURE_PAIRS[@]}" -eq 0 ]; then
|
||||
echo " Detected: none" >&2
|
||||
else
|
||||
printf ' Detected: %s\n' "${GC_VIDEOS[@]}" >&2
|
||||
printf ' Detected: %s\n' "${GC_CAPTURE_PAIRS[@]}" >&2
|
||||
fi
|
||||
echo " The server install will continue, and existing /dev/lesavka_* links stay untouched." >&2
|
||||
else
|
||||
mapfile -t TAGS < <(
|
||||
for v in "${GC_VIDEOS[@]}"; do
|
||||
sudo udevadm info -q property -n "$v" |
|
||||
awk -F= '/^ID_PATH_TAG=/{print $2}'
|
||||
done
|
||||
)
|
||||
LEFT_TAG=${GC_CAPTURE_PAIRS[0]%% *}
|
||||
LEFT_DEV=${GC_CAPTURE_PAIRS[0]#* }
|
||||
RIGHT_TAG=${GC_CAPTURE_PAIRS[1]%% *}
|
||||
RIGHT_DEV=${GC_CAPTURE_PAIRS[1]#* }
|
||||
|
||||
if [ -z "${TAGS[0]:-}" ] || [ -z "${TAGS[1]:-}" ]; then
|
||||
echo "⚠️ GC311 cards were detected, but ID_PATH_TAG lookup was incomplete." >&2
|
||||
if [ -z "$LEFT_TAG" ] || [ -z "$RIGHT_TAG" ] || [ "$LEFT_TAG" = "$RIGHT_TAG" ]; then
|
||||
echo "⚠️ GC311 cards were detected, but the capture path tags are incomplete or duplicated." >&2
|
||||
printf ' Left candidate: %s\n' "${GC_CAPTURE_PAIRS[0]:-missing}" >&2
|
||||
printf ' Right candidate: %s\n' "${GC_CAPTURE_PAIRS[1]:-missing}" >&2
|
||||
echo " Skipping udev eye-link refresh and preserving any existing /dev/lesavka_* links." >&2
|
||||
else
|
||||
printf ' ↪ Left card: %s (%s)\n' "${GC_VIDEOS[0]}" "${TAGS[0]}"
|
||||
printf ' ↪ Right card: %s (%s)\n' "${GC_VIDEOS[1]}" "${TAGS[1]}"
|
||||
|
||||
LEFT_TAG=${TAGS[0]}
|
||||
RIGHT_TAG=${TAGS[1]}
|
||||
printf ' ↪ Left card: %s (%s)\n' "$LEFT_DEV" "$LEFT_TAG"
|
||||
printf ' ↪ Right card: %s (%s)\n' "$RIGHT_DEV" "$RIGHT_TAG"
|
||||
|
||||
sudo tee /etc/udev/rules.d/85-gc311.rules >/dev/null <<EOF
|
||||
# auto-generated by lesavka/scripts/daemon/install-server.sh - DO NOT EDIT
|
||||
|
||||
@ -10,7 +10,7 @@ bench = false
|
||||
|
||||
[package]
|
||||
name = "lesavka_server"
|
||||
version = "0.13.15"
|
||||
version = "0.13.16"
|
||||
edition = "2024"
|
||||
autobins = false
|
||||
|
||||
|
||||
@ -55,3 +55,19 @@ fn server_install_grants_operator_audio_group_access() {
|
||||
"install script should target the sudo-invoking operator instead of a hard-coded account"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn server_install_builds_eye_links_from_capture_nodes_only() {
|
||||
assert!(
|
||||
SERVER_INSTALL.contains("/sys/class/video4linux/$(basename \"$dev\")/index"),
|
||||
"install script should inspect the kernel video index so it only links real capture nodes"
|
||||
);
|
||||
assert!(
|
||||
SERVER_INSTALL.contains("GC_CAPTURE_PAIRS"),
|
||||
"install script should assemble eye-link candidates from udev-tagged capture devices"
|
||||
);
|
||||
assert!(
|
||||
SERVER_INSTALL.contains("[ \"$LEFT_TAG\" = \"$RIGHT_TAG\" ]"),
|
||||
"install script should refuse duplicated path tags instead of assigning both eyes to one card"
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user