mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-01-18 03:28:19 +01:00
Update App version to 0.0.2
This commit is contained in:
@@ -34,6 +34,7 @@ const (
|
||||
FileStateFileWrite // update file content without checking
|
||||
FileStateMounted
|
||||
FileStateMountedConfigFS
|
||||
FileStateMountedFunctionFS
|
||||
FileStateSymlink
|
||||
FileStateSymlinkInOrderConfigFS // configfs is a shithole, so we need to check if the symlinks are created in the correct order
|
||||
FileStateSymlinkNotInOrderConfigFS
|
||||
@@ -52,6 +53,7 @@ var FileStateString = map[FileState]string{
|
||||
FileStateSymlink: "SYMLINK",
|
||||
FileStateSymlinkInOrderConfigFS: "SYMLINK_IN_ORDER_CONFIGFS",
|
||||
FileStateTouch: "TOUCH",
|
||||
FileStateMountedFunctionFS: "FUNCTIONFS_MOUNTED",
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -78,6 +80,7 @@ const (
|
||||
FileChangeResolvedActionRemoveDirectory
|
||||
FileChangeResolvedActionTouch
|
||||
FileChangeResolvedActionMountConfigFS
|
||||
FileChangeResolvedActionMountFunctionFS
|
||||
)
|
||||
|
||||
var FileChangeResolvedActionString = map[FileChangeResolvedAction]string{
|
||||
@@ -96,6 +99,7 @@ var FileChangeResolvedActionString = map[FileChangeResolvedAction]string{
|
||||
FileChangeResolvedActionRemoveDirectory: "DIR_REMOVE",
|
||||
FileChangeResolvedActionTouch: "TOUCH",
|
||||
FileChangeResolvedActionMountConfigFS: "CONFIGFS_MOUNT",
|
||||
FileChangeResolvedActionMountFunctionFS: "FUNCTIONFS_MOUNT",
|
||||
}
|
||||
|
||||
type ChangeSet struct {
|
||||
@@ -147,6 +151,8 @@ func (f *RequestedFileChange) String() string {
|
||||
s = fmt.Sprintf("write: %s with content [%s]", f.Path, f.ExpectedContent)
|
||||
case FileStateMountedConfigFS:
|
||||
s = fmt.Sprintf("configfs: %s", f.Path)
|
||||
case FileStateMountedFunctionFS:
|
||||
s = fmt.Sprintf("functionfs: %s", f.Path)
|
||||
case FileStateTouch:
|
||||
s = fmt.Sprintf("touch: %s", f.Path)
|
||||
case FileStateUnknown:
|
||||
@@ -298,6 +304,8 @@ func (fc *FileChange) getFileChangeResolvedAction() FileChangeResolvedAction {
|
||||
return FileChangeResolvedActionWriteFile
|
||||
case FileStateTouch:
|
||||
return FileChangeResolvedActionTouch
|
||||
case FileStateMountedFunctionFS:
|
||||
return FileChangeResolvedActionMountFunctionFS
|
||||
}
|
||||
|
||||
// get the actual state of the file
|
||||
@@ -424,6 +432,8 @@ func (c *ChangeSet) applyChange(change *FileChange) error {
|
||||
return os.Chtimes(change.Path, time.Now(), time.Now())
|
||||
case FileChangeResolvedActionMountConfigFS:
|
||||
return mountConfigFS(change.Path)
|
||||
case FileChangeResolvedActionMountFunctionFS:
|
||||
return mountFunctionFS(change.Path)
|
||||
case FileChangeResolvedActionDoNothing:
|
||||
return nil
|
||||
default:
|
||||
|
||||
@@ -2,6 +2,7 @@ package usbgadget
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sourcegraph/tf-dag/dag"
|
||||
@@ -127,6 +128,11 @@ func (c *ChangeSetResolver) applyChanges() error {
|
||||
l.Str("action", actionStr).Str("change", change.String()).Msg("applying change")
|
||||
|
||||
err := c.changeset.applyChange(change)
|
||||
if err != nil {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
err = c.changeset.applyChange(change)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if change.IgnoreErrors {
|
||||
c.l.Warn().Str("change", change.String()).Err(err).Msg("ignoring error")
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package usbgadget
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type gadgetConfigItem struct {
|
||||
@@ -51,6 +54,8 @@ var defaultGadgetConfig = map[string]gadgetConfigItem{
|
||||
"configuration": "Config 1: HID",
|
||||
},
|
||||
},
|
||||
// mtp
|
||||
"mtp": mtpConfig,
|
||||
// keyboard HID
|
||||
"keyboard": keyboardConfig,
|
||||
// mouse HID
|
||||
@@ -91,6 +96,8 @@ func (u *UsbGadget) isGadgetConfigItemEnabled(itemKey string) bool {
|
||||
return u.enabledDevices.MassStorage
|
||||
case "mass_storage_lun0":
|
||||
return u.enabledDevices.MassStorage
|
||||
case "mtp":
|
||||
return u.enabledDevices.Mtp
|
||||
case "audio":
|
||||
return u.enabledDevices.Audio
|
||||
default:
|
||||
@@ -184,6 +191,45 @@ func mountConfigFS(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mountFunctionFS(path string) error {
|
||||
err := os.MkdirAll("/dev/ffs-mtp", 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create mtp dev dir: %w", err)
|
||||
}
|
||||
mounted := false
|
||||
if f, err := os.Open("/proc/mounts"); err == nil {
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
if strings.Contains(scanner.Text(), functionFSPath) {
|
||||
mounted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
f.Close()
|
||||
}
|
||||
|
||||
if !mounted {
|
||||
err := exec.Command("mount", "-t", "functionfs", "mtp", path).Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to mount functionfs: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
umtprdRunning := false
|
||||
if out, err := exec.Command("pgrep", "-x", "umtprd").Output(); err == nil && len(out) > 0 {
|
||||
umtprdRunning = true
|
||||
}
|
||||
|
||||
if !umtprdRunning {
|
||||
cmd := exec.Command("umtprd")
|
||||
if err := cmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to exec binary: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *UsbGadget) Init() error {
|
||||
u.configLock.Lock()
|
||||
defer u.configLock.Unlock()
|
||||
|
||||
@@ -131,6 +131,16 @@ func (tx *UsbGadgetTransaction) MountConfigFS() {
|
||||
})
|
||||
}
|
||||
|
||||
func (tx *UsbGadgetTransaction) MountFunctionFS() {
|
||||
tx.addFileChange("mtp", RequestedFileChange{
|
||||
Path: functionFSPath,
|
||||
Key: "mtp",
|
||||
ExpectedState: FileStateMountedFunctionFS,
|
||||
Description: "mount functionfs",
|
||||
DependsOn: []string{"reorder-symlinks"},
|
||||
})
|
||||
}
|
||||
|
||||
func (tx *UsbGadgetTransaction) CreateConfigPath() {
|
||||
tx.mkdirAll(
|
||||
"gadget",
|
||||
@@ -164,7 +174,12 @@ func (tx *UsbGadgetTransaction) WriteGadgetConfig() {
|
||||
deps = tx.writeGadgetItemConfig(item, deps)
|
||||
}
|
||||
|
||||
tx.WriteUDC()
|
||||
if tx.isGadgetConfigItemEnabled("mtp") {
|
||||
tx.MountFunctionFS()
|
||||
tx.WriteUDC(true)
|
||||
} else {
|
||||
tx.WriteUDC(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (tx *UsbGadgetTransaction) getDisableKeys() []string {
|
||||
@@ -315,17 +330,28 @@ func (tx *UsbGadgetTransaction) addReorderSymlinkChange(path string, target stri
|
||||
})
|
||||
}
|
||||
|
||||
func (tx *UsbGadgetTransaction) WriteUDC() {
|
||||
func (tx *UsbGadgetTransaction) WriteUDC(mtpServer bool) {
|
||||
// bound the gadget to a UDC (USB Device Controller)
|
||||
path := path.Join(tx.kvmGadgetPath, "UDC")
|
||||
tx.addFileChange("udc", RequestedFileChange{
|
||||
Key: "udc",
|
||||
Path: path,
|
||||
ExpectedState: FileStateFileContentMatch,
|
||||
ExpectedContent: []byte(tx.udc),
|
||||
DependsOn: []string{"reorder-symlinks"},
|
||||
Description: "write UDC",
|
||||
})
|
||||
if mtpServer {
|
||||
tx.addFileChange("udc", RequestedFileChange{
|
||||
Key: "udc",
|
||||
Path: path,
|
||||
ExpectedState: FileStateFileContentMatch,
|
||||
ExpectedContent: []byte(tx.udc),
|
||||
DependsOn: []string{"mtp"},
|
||||
Description: "write UDC",
|
||||
})
|
||||
} else {
|
||||
tx.addFileChange("udc", RequestedFileChange{
|
||||
Key: "udc",
|
||||
Path: path,
|
||||
ExpectedState: FileStateFileContentMatch,
|
||||
ExpectedContent: []byte(tx.udc),
|
||||
DependsOn: []string{"reorder-symlinks"},
|
||||
Description: "write UDC",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (tx *UsbGadgetTransaction) RebindUsb(ignoreUnbindError bool) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
package usbgadget
|
||||
|
||||
const dwc3Path = "/sys/bus/platform/drivers/dwc3"
|
||||
const udcPath = "/sys/kernel/config/usb_gadget/kvm/UDC"
|
||||
|
||||
@@ -23,3 +23,10 @@ var massStorageLun0Config = gadgetConfigItem{
|
||||
"inquiry_string": "KVM Virtual Media",
|
||||
},
|
||||
}
|
||||
|
||||
var mtpConfig = gadgetConfigItem{
|
||||
order: 3003,
|
||||
device: "ffs.mtp",
|
||||
path: []string{"functions", "ffs.mtp"},
|
||||
configPath: []string{"ffs.mtp"},
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func (u *UsbGadget) IsUDCBound() (bool, error) {
|
||||
|
||||
// BindUDC binds the gadget to the UDC.
|
||||
func (u *UsbGadget) BindUDC() error {
|
||||
err := os.WriteFile(path.Join(dwc3Path, "bind"), []byte(u.udc), 0644)
|
||||
err := os.WriteFile(path.Join(udcPath, "bind"), []byte(u.udc), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error binding UDC: %w", err)
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func (u *UsbGadget) BindUDC() error {
|
||||
|
||||
// UnbindUDC unbinds the gadget from the UDC.
|
||||
func (u *UsbGadget) UnbindUDC() error {
|
||||
err := os.WriteFile(path.Join(dwc3Path, "unbind"), []byte(u.udc), 0644)
|
||||
err := os.WriteFile(path.Join(udcPath, " "), []byte(u.udc), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unbinding UDC: %w", err)
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ type Devices struct {
|
||||
RelativeMouse bool `json:"relative_mouse"`
|
||||
Keyboard bool `json:"keyboard"`
|
||||
MassStorage bool `json:"mass_storage"`
|
||||
Mtp bool `json:"mtp"`
|
||||
Audio bool `json:"audio"`
|
||||
}
|
||||
|
||||
@@ -88,6 +89,9 @@ type UsbGadget struct {
|
||||
const configFSPath = "/sys/kernel/config"
|
||||
const gadgetPath = "/sys/kernel/config/usb_gadget"
|
||||
|
||||
const functionFSPath = "/dev/ffs-mtp"
|
||||
const umtprdPath = "/usr/sbin/umtprd"
|
||||
|
||||
var defaultLogger = logging.GetSubsystemLogger("usbgadget")
|
||||
|
||||
// NewUsbGadget creates a new UsbGadget.
|
||||
|
||||
Reference in New Issue
Block a user