Update App version to 0.0.2

This commit is contained in:
luckfox-eng29
2025-09-16 11:03:46 +08:00
parent 8fbd6bcf0d
commit 15d276652c
45 changed files with 3347 additions and 252 deletions

View File

@@ -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:

View File

@@ -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")

View File

@@ -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()

View File

@@ -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) {

View File

@@ -1,3 +1,4 @@
package usbgadget
const dwc3Path = "/sys/bus/platform/drivers/dwc3"
const udcPath = "/sys/kernel/config/usb_gadget/kvm/UDC"

View File

@@ -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"},
}

View File

@@ -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)
}

View File

@@ -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.