fixes
This commit is contained in:
parent
4b497ffa16
commit
60cee23d08
@ -1,130 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# install-server.sh - install and setup all server related apps and environments
|
|
||||||
set -euo pipefail
|
|
||||||
ORIG_USER=${SUDO_USER:-$(id -un)}
|
|
||||||
|
|
||||||
echo "==> 1a. Base packages"
|
|
||||||
sudo pacman -Syq --needed --noconfirm git rustup protobuf gcc pipewire pipewire-pulse tailscale base-devel gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav
|
|
||||||
if ! command -v yay >/dev/null 2>&1; then
|
|
||||||
echo "==> 1b. installing yay from AUR ..."
|
|
||||||
sudo -u "$ORIG_USER" bash -c '
|
|
||||||
cd /tmp && git clone --depth 1 https://aur.archlinux.org/yay.git &&
|
|
||||||
cd yay && makepkg -si --noconfirm'
|
|
||||||
fi
|
|
||||||
yay -S --noconfirm grpcurl-bin
|
|
||||||
|
|
||||||
echo "==> 2a. Kernel-driver tweaks"
|
|
||||||
cat <<'EOF' | sudo tee /etc/modprobe.d/gc311-stream.conf >/dev/null
|
|
||||||
options uvcvideo quirks=0x200 timeout=10000
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "==> 2b. Predictable /dev names for each capture card"
|
|
||||||
# probe all v4l2 devices, keep only the two GC311 capture cards
|
|
||||||
mapfile -t GC_VIDEOS < <(
|
|
||||||
sudo v4l2-ctl --list-devices |
|
|
||||||
awk '/Live Gamer MINI/{getline; print $1}'
|
|
||||||
)
|
|
||||||
|
|
||||||
if [ "${#GC_VIDEOS[@]}" -ne 2 ]; then
|
|
||||||
echo "❌ Exactly two GC311 capture cards (index0) must be attached!" >&2
|
|
||||||
printf ' Detected: %s\n' "${GC_VIDEOS[@]}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mapfile -t TAGS < <(
|
|
||||||
for v in "${GC_VIDEOS[@]}"; do
|
|
||||||
sudo udevadm info -q property -n "$v" |
|
|
||||||
awk -F= '/^ID_PATH_TAG=/{print $2}'
|
|
||||||
done
|
|
||||||
)
|
|
||||||
|
|
||||||
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]}
|
|
||||||
|
|
||||||
sudo tee /etc/udev/rules.d/85-gc311.rules >/dev/null <<EOF
|
|
||||||
# auto-generated by lesavka/scripts/install-server.sh - DO NOT EDIT
|
|
||||||
SUBSYSTEM=="video4linux", ENV{ID_PATH_TAG}=="$LEFT_TAG", SYMLINK+="lesavka_l_eye"
|
|
||||||
SUBSYSTEM=="video4linux", ENV{ID_PATH_TAG}=="$RIGHT_TAG", SYMLINK+="lesavka_r_eye"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo udevadm control --reload
|
|
||||||
sudo udevadm trigger --subsystem-match=video4linux
|
|
||||||
sudo udevadm settle
|
|
||||||
|
|
||||||
echo "==> 3. Rust toolchain"
|
|
||||||
sudo rustup default stable
|
|
||||||
sudo -u "$ORIG_USER" rustup default stable
|
|
||||||
|
|
||||||
echo "==> 4a. Source checkout"
|
|
||||||
SRC_DIR=/var/src/lesavka
|
|
||||||
REPO_URL=ssh://git@scm.bstein.dev:2242/brad_stein/lesavka.git
|
|
||||||
if [[ ! -d $SRC_DIR ]]; then
|
|
||||||
sudo mkdir -p /var/src
|
|
||||||
sudo chown "$ORIG_USER":"$ORIG_USER" /var/src
|
|
||||||
fi
|
|
||||||
if [[ -d $SRC_DIR/.git ]]; then
|
|
||||||
sudo -u "$ORIG_USER" git -C "$SRC_DIR" pull --ff-only
|
|
||||||
else
|
|
||||||
sudo -u "$ORIG_USER" git clone "$REPO_URL" "$SRC_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "==> 4b. Source build"
|
|
||||||
sudo -u "$ORIG_USER" bash -c "cd '$SRC_DIR/server' && cargo clean && cargo build --release"
|
|
||||||
|
|
||||||
echo "==> 5. Install binaries"
|
|
||||||
sudo install -Dm755 "$SRC_DIR/server/target/release/lesavka-server" /usr/local/bin/lesavka-server
|
|
||||||
sudo install -Dm755 "$SRC_DIR/scripts/lesavka-core.sh" /usr/local/bin/lesavka-core.sh
|
|
||||||
|
|
||||||
echo "==> 6a. Systemd units - lesavka-core"
|
|
||||||
cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-core.service >/dev/null
|
|
||||||
[Unit]
|
|
||||||
Description=lesavka USB gadget bring-up
|
|
||||||
After=sys-kernel-config.mount
|
|
||||||
Requires=sys-kernel-config.mount
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
ExecStart=/usr/local/bin/lesavka-core.sh
|
|
||||||
RemainAfterExit=yes
|
|
||||||
CapabilityBoundingSet=CAP_SYS_ADMIN
|
|
||||||
MountFlags=slave
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
UNIT
|
|
||||||
|
|
||||||
echo "==> 6b. Systemd units - lesavka-server"
|
|
||||||
cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-server.service >/dev/null
|
|
||||||
[Unit]
|
|
||||||
Description=lesavka gRPC relay
|
|
||||||
After=network.target lesavka-core.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStart=/usr/local/bin/lesavka-server
|
|
||||||
Restart=always
|
|
||||||
Environment=RUST_LOG=lesavka_server=debug,lesavka_server::usb_gadget=info
|
|
||||||
Environment=RUST_BACKTRACE=1
|
|
||||||
Restart=always
|
|
||||||
RestartSec=5
|
|
||||||
StandardError=append:/tmp/lesavka-server.log
|
|
||||||
StartLimitIntervalSec=30
|
|
||||||
StartLimitBurst=10
|
|
||||||
User=root
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
UNIT
|
|
||||||
|
|
||||||
echo "==> 6c. Systemd units - initialization"
|
|
||||||
sudo truncate -s 0 /tmp/lesavka-server.log
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable --now lesavka-core
|
|
||||||
sudo systemctl restart lesavka-core
|
|
||||||
echo "✅ lesavka-core installed and restarted..."
|
|
||||||
|
|
||||||
sudo systemctl enable --now lesavka-server
|
|
||||||
sudo systemctl restart lesavka-server
|
|
||||||
echo "✅ lesavka-server installed and restarted..."
|
|
||||||
@ -105,7 +105,7 @@ After=network.target lesavka-core.service
|
|||||||
[Service]
|
[Service]
|
||||||
ExecStart=/usr/local/bin/lesavka-server
|
ExecStart=/usr/local/bin/lesavka-server
|
||||||
Restart=always
|
Restart=always
|
||||||
Environment=RUST_LOG=lesavka_server=info,lesavka_server::video=trace,lesavka_server::usb_gadget=info
|
Environment=RUST_LOG=lesavka_server=trace,lesavka_server::video=trace,lesavka_server::usb_gadget=info
|
||||||
Environment=RUST_BACKTRACE=1
|
Environment=RUST_BACKTRACE=1
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|||||||
@ -1,114 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# lesavka-core.sh - background stealth daemon to present gadget as usb hub of genuine devices
|
|
||||||
# Proven Pi-5 configfs gadget: HID keyboard+mouse
|
|
||||||
# Still need Web Cam Support + stereo UAC2
|
|
||||||
|
|
||||||
# lesavka-core - one-shot gadget bring-up for Pi-5 / Arch-ARM
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# 1) Ensure the dwc2 peripheral overlay is active exactly once
|
|
||||||
CFG=/boot/config.txt
|
|
||||||
grep -q 'dtoverlay=dwc2,dr_mode=peripheral' "$CFG" || echo 'dtoverlay=dwc2,dr_mode=peripheral' >> "$CFG"
|
|
||||||
|
|
||||||
# 2) Load kernel modules (idempotent)
|
|
||||||
modprobe dwc2 || { echo "dwc2 not in kernel; abort" >&2; exit 1; }
|
|
||||||
modprobe libcomposite || { echo "libcomposite not in kernel; abort" >&2; exit 1; }
|
|
||||||
|
|
||||||
modprobe -r uvcvideo 2>/dev/null || true
|
|
||||||
modprobe uvcvideo || { echo "uvcvideo not in kernel; abort" >&2; exit 1; }
|
|
||||||
|
|
||||||
udevadm control --reload
|
|
||||||
udevadm trigger --subsystem-match=video4linux
|
|
||||||
udevadm settle
|
|
||||||
|
|
||||||
echo "[lesavka-core] ⏳ waiting for UDC to register ..."
|
|
||||||
UDC=""
|
|
||||||
for _ in {1..100}; do # 100 × 100ms = 10s
|
|
||||||
UDC=$(ls /sys/class/udc 2>/dev/null | head -n1) && [[ -n $UDC ]] && break
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z $UDC ]]; then
|
|
||||||
echo "[lesavka-core] ⚠️ UDC still absent - trying manual bind"
|
|
||||||
for drv in dwc2 dwc3; do
|
|
||||||
drv_root="/sys/bus/platform/drivers/$drv"
|
|
||||||
[[ -d $drv_root ]] || continue
|
|
||||||
for node in /sys/bus/platform/devices/*usb*; do
|
|
||||||
node=${node##*/} # strip path → “1000480000.usb”
|
|
||||||
echo "$node" >"$drv_root/bind" 2>/dev/null || continue
|
|
||||||
done
|
|
||||||
done
|
|
||||||
# re-check for another 5 s
|
|
||||||
for i in {1..50}; do
|
|
||||||
UDC=$(ls /sys/class/udc 2>/dev/null | head -n1) && [[ -n $UDC ]] && break
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -n $UDC ]] || { echo "❌ UDC not present after manual bind"; exit 1; }
|
|
||||||
echo "[lesavka-core] ✅ UDC detected: $UDC"
|
|
||||||
|
|
||||||
# 3) Mount configfs once
|
|
||||||
mountpoint -q /sys/kernel/config || mount -t configfs none /sys/kernel/config
|
|
||||||
G=/sys/kernel/config/usb_gadget/lesavka
|
|
||||||
|
|
||||||
# 4) Tear down any previous half-built gadget
|
|
||||||
if [[ -d $G ]]; then
|
|
||||||
echo '' >"$G/UDC" 2>/dev/null || true
|
|
||||||
sleep 0.2
|
|
||||||
find "$G/configs" -type l -delete 2>/dev/null || true
|
|
||||||
rm -rf "$G" 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 5) Create gadget (boot-keyboard + UAC2 mic/spkr, 500 mA max)
|
|
||||||
mkdir -p "$G"
|
|
||||||
echo 0x1d6b >"$G/idVendor" # Linux Foundation
|
|
||||||
echo 0x0104 >"$G/idProduct" # Multifunction Composite Gadget
|
|
||||||
echo 0x0200 >"$G/bcdUSB"
|
|
||||||
|
|
||||||
mkdir -p "$G/strings/0x409"
|
|
||||||
echo "$(cat /proc/sys/kernel/random/uuid)" >"$G/strings/0x409/serialnumber"
|
|
||||||
echo "Lesavka" >"$G/strings/0x409/manufacturer"
|
|
||||||
echo "Lesavka Composite" >"$G/strings/0x409/product"
|
|
||||||
|
|
||||||
# ----------------------- HID keyboard (usb0) -----------------------
|
|
||||||
mkdir -p "$G/functions/hid.usb0"
|
|
||||||
echo 1 >"$G/functions/hid.usb0/protocol"
|
|
||||||
echo 1 >"$G/functions/hid.usb0/subclass"
|
|
||||||
echo 8 >"$G/functions/hid.usb0/report_length"
|
|
||||||
printf '\x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01'\
|
|
||||||
'\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x95\x05\x75\x01\x05'\
|
|
||||||
'\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x01\x95\x06\x75\x08'\
|
|
||||||
'\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xc0' \
|
|
||||||
>"$G/functions/hid.usb0/report_desc"
|
|
||||||
|
|
||||||
# ----------------------- HID mouse (usb1) --------------------------
|
|
||||||
mkdir -p "$G/functions/hid.usb1"
|
|
||||||
echo 2 > "$G/functions/hid.usb1/protocol" # Boot mouse
|
|
||||||
echo 1 > "$G/functions/hid.usb1/subclass"
|
|
||||||
echo 4 > "$G/functions/hid.usb1/report_length"
|
|
||||||
printf '\x05\x01\x09\x02\xa1\x01\x09\x01\xa1\x00'\
|
|
||||||
'\x05\x09\x19\x01\x29\x03\x15\x00\x25\x01\x95\x03\x75\x01\x81\x02'\
|
|
||||||
'\x95\x01\x75\x05\x81\x03'\
|
|
||||||
'\x05\x01\x09\x30\x09\x31\x09\x38\x15\x81\x25\x7f\x75\x08\x95\x03\x81\x06'\
|
|
||||||
'\xc0\xc0' >"$G/functions/hid.usb1/report_desc"
|
|
||||||
|
|
||||||
# # -- UAC2 Audio
|
|
||||||
# mkdir -p $G/functions/uac2.usb0
|
|
||||||
# echo 48000 > $G/functions/uac2.usb0/c_srate
|
|
||||||
# echo 2 > $G/functions/uac2.usb0/c_ssize
|
|
||||||
# echo 2 > $G/functions/uac2.usb0/p_chmask
|
|
||||||
|
|
||||||
# ----------------------- configuration -----------------------------
|
|
||||||
mkdir -p "$G/configs/c.1/strings/0x409"
|
|
||||||
echo 500 > "$G/configs/c.1/MaxPower"
|
|
||||||
echo "Config 1" > "$G/configs/c.1/strings/0x409/configuration"
|
|
||||||
|
|
||||||
# 6) Finally bind to first available UDC
|
|
||||||
ln -s $G/functions/hid.usb0 $G/configs/c.1/
|
|
||||||
ln -s $G/functions/hid.usb1 $G/configs/c.1/
|
|
||||||
# ln -s $G/functions/uac2.usb0 $G/configs/c.1/
|
|
||||||
|
|
||||||
# 7) Finally bind to first available UDC
|
|
||||||
echo "$UDC" > "$G/UDC"
|
|
||||||
echo "[lesavka-core] 🎉 gadget ready on $UDC (keyboard: hidg0, mouse: hidg1)"
|
|
||||||
@ -34,7 +34,7 @@ const AUTO_CYCLE: bool = false;
|
|||||||
/*──────────────── logging ───────────────────*/
|
/*──────────────── logging ───────────────────*/
|
||||||
fn init_tracing() -> anyhow::Result<WorkerGuard> {
|
fn init_tracing() -> anyhow::Result<WorkerGuard> {
|
||||||
let file = std::fs::OpenOptions::new()
|
let file = std::fs::OpenOptions::new()
|
||||||
.create(true).append(true).write(true)
|
.create(true).truncate(true).write(true)
|
||||||
.open("/tmp/lesavka-server.log")?;
|
.open("/tmp/lesavka-server.log")?;
|
||||||
let (file_writer, guard) = tracing_appender::non_blocking(file);
|
let (file_writer, guard) = tracing_appender::non_blocking(file);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user