84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
//go:build linux
|
|
|
|
package client
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// createSocketPair creates a Unix domain socket pair
|
|
func createSocketPair() ([2]int, error) {
|
|
fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0)
|
|
if err != nil {
|
|
return [2]int{}, fmt.Errorf("socketpair: %w", err)
|
|
}
|
|
return fds, nil
|
|
}
|
|
|
|
func closeFDs(fds [2]int) {
|
|
unix.Close(fds[0])
|
|
unix.Close(fds[1])
|
|
}
|
|
|
|
func fdToFile(fd int, name string) *os.File {
|
|
return os.NewFile(uintptr(fd), name)
|
|
}
|
|
|
|
// fixVHCIDevicePermissions waits for the VHCI-attached device to create
|
|
// device nodes (e.g. /dev/video*) and sets them to world-accessible.
|
|
// VHCI-created devices don't get normal udev rules applied, so they
|
|
// default to root-only access.
|
|
func fixVHCIDevicePermissions(port int) {
|
|
// Wait for the device to finish enumerating and create device nodes
|
|
// The kernel needs time to enumerate descriptors and bind drivers
|
|
for attempt := 0; attempt < 10; attempt++ {
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
// Find device nodes created by this VHCI port
|
|
// VHCI creates devices under /sys/devices/platform/vhci_hcd.0/usbN/
|
|
// We look for video4linux devices
|
|
matches, _ := filepath.Glob("/sys/devices/platform/vhci_hcd.0/usb*/*/video4linux/video*")
|
|
for _, m := range matches {
|
|
devName := filepath.Base(m)
|
|
devPath := "/dev/" + devName
|
|
if _, err := os.Stat(devPath); err == nil {
|
|
if err := os.Chmod(devPath, 0666); err == nil {
|
|
log.Printf("[use] set permissions 0666 on %s", devPath)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also check for other common device types (input, sound, etc.)
|
|
for _, subsys := range []string{"sound/card*", "input/input*/event*"} {
|
|
sysMatches, _ := filepath.Glob("/sys/devices/platform/vhci_hcd.0/usb*/*/" + subsys)
|
|
for _, m := range sysMatches {
|
|
devName := filepath.Base(m)
|
|
devPath := "/dev/" + devName
|
|
// For sound devices, also check /dev/snd/
|
|
if _, err := os.Stat(devPath); err == nil {
|
|
os.Chmod(devPath, 0666)
|
|
}
|
|
devPath = "/dev/snd/" + devName
|
|
if _, err := os.Stat(devPath); err == nil {
|
|
os.Chmod(devPath, 0666)
|
|
}
|
|
}
|
|
}
|
|
|
|
if attempt == 0 {
|
|
continue // first iteration: always wait more
|
|
}
|
|
|
|
// Check if we found any video devices
|
|
if len(matches) > 0 {
|
|
return
|
|
}
|
|
}
|
|
}
|