This commit is contained in:
Aveline 2025-11-17 15:54:39 +01:00 committed by GitHub
commit 31c642f64b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 25 deletions

View File

@ -24,6 +24,14 @@ type gadgetConfigItemWithKey struct {
type orderedGadgetConfigItems []gadgetConfigItemWithKey
type UsbResetMode uint8
const (
UsbResetNever UsbResetMode = 0 // never reset the usb gadget
UsbResetAlways UsbResetMode = 1 // always reset the usb gadget
UsbResetOnDemand UsbResetMode = 2 // reset the usb gadget when needed
)
var defaultGadgetConfig = map[string]gadgetConfigItem{
"base": {
order: 0,
@ -177,7 +185,7 @@ func (u *UsbGadget) Init() error {
u.udc = udcs[0]
err := u.configureUsbGadget(false)
err := u.configureUsbGadget(UsbResetAlways)
if err != nil {
return u.logError("unable to initialize USB stack", err)
}
@ -185,13 +193,13 @@ func (u *UsbGadget) Init() error {
return nil
}
func (u *UsbGadget) UpdateGadgetConfig() error {
func (u *UsbGadget) UpdateGadgetConfig(resetUsbMode UsbResetMode) error {
u.configLock.Lock()
defer u.configLock.Unlock()
u.loadGadgetConfig()
err := u.configureUsbGadget(true)
err := u.configureUsbGadget(resetUsbMode)
if err != nil {
return u.logError("unable to update gadget config", err)
}
@ -199,14 +207,35 @@ func (u *UsbGadget) UpdateGadgetConfig() error {
return nil
}
func (u *UsbGadget) configureUsbGadget(resetUsb bool) error {
return u.WithTransaction(func() error {
u.tx.MountConfigFS()
u.tx.CreateConfigPath()
u.tx.WriteGadgetConfig()
if resetUsb {
u.tx.RebindUsb(true)
func (u *UsbGadget) configureUsbGadget(resetUsbMode UsbResetMode) error {
f := func(resetUsbAfter bool) func() error {
return func() error {
u.tx.MountConfigFS()
u.tx.CreateConfigPath()
u.tx.WriteGadgetConfig()
if resetUsbAfter {
u.tx.RebindUsb(true)
}
return nil
}
}
// initial attempt to configure the gadget
err := u.WithTransaction(f(resetUsbMode == UsbResetAlways))
if err == nil {
return nil
})
}
// if the initial attempt failed, try to configure the gadget again with the resetUsb flag
if resetUsbMode == UsbResetOnDemand {
u.log.Warn().Err(err).Msg("initial attempt to configure the gadget failed, resetting USB gadget then trying again")
// NOTES: do not use the RebindUsb method here because it will block the transaction
if err := u.rebindUsb(true); err != nil {
u.log.Warn().Err(err).Msg("failed to reset USB gadget, skipping second attempt")
return err
}
return u.WithTransaction(f(true))
}
return err
}

View File

@ -678,7 +678,7 @@ func rpcSetUsbConfig(usbConfig usbgadget.Config) error {
LoadConfig()
config.UsbConfig = &usbConfig
gadget.SetGadgetConfig(config.UsbConfig)
return updateUsbRelatedConfig()
return updateUsbRelatedConfig(usbgadget.UsbResetAlways)
}
func rpcGetWakeOnLanDevices() ([]WakeOnLanDevice, error) {
@ -890,8 +890,8 @@ func rpcGetUsbDevices() (usbgadget.Devices, error) {
return *config.UsbDevices, nil
}
func updateUsbRelatedConfig() error {
if err := gadget.UpdateGadgetConfig(); err != nil {
func updateUsbRelatedConfig(resetUsbMode usbgadget.UsbResetMode) error {
if err := gadget.UpdateGadgetConfig(resetUsbMode); err != nil {
return fmt.Errorf("failed to write gadget config: %w", err)
}
if err := SaveConfig(); err != nil {
@ -903,7 +903,7 @@ func updateUsbRelatedConfig() error {
func rpcSetUsbDevices(usbDevices usbgadget.Devices) error {
config.UsbDevices = &usbDevices
gadget.SetGadgetDevices(config.UsbDevices)
return updateUsbRelatedConfig()
return updateUsbRelatedConfig(usbgadget.UsbResetOnDemand)
}
func rpcSetUsbDeviceState(device string, enabled bool) error {
@ -920,7 +920,7 @@ func rpcSetUsbDeviceState(device string, enabled bool) error {
return fmt.Errorf("invalid device: %s", device)
}
gadget.SetGadgetDevices(config.UsbDevices)
return updateUsbRelatedConfig()
return updateUsbRelatedConfig(usbgadget.UsbResetAlways)
}
func rpcSetCloudUrl(apiUrl string, appUrl string) error {

View File

@ -6,6 +6,7 @@ import { Button } from "@components/Button";
import { useFailsafeModeStore } from "@/hooks/stores";
import { sleep } from "@/utils";
import { m } from "@localizations/messages.js";
import { sleep } from "@/utils";
import LoadingSpinner from "../components/LoadingSpinner";
import { useDeviceUiNavigation } from "../hooks/useAppNavigation";

View File

@ -19,13 +19,10 @@ import (
"github.com/pion/webrtc/v4"
"github.com/psanford/httpreadat"
"github.com/jetkvm/kvm/internal/usbgadget"
"github.com/jetkvm/kvm/resource"
)
func writeFile(path string, data string) error {
return os.WriteFile(path, []byte(data), 0644)
}
func getMassStorageImage() (string, error) {
massStorageFunctionPath, err := gadget.GetPath("mass_storage_lun0")
if err != nil {
@ -40,14 +37,15 @@ func getMassStorageImage() (string, error) {
}
func setMassStorageImage(imagePath string) error {
massStorageFunctionPath, err := gadget.GetPath("mass_storage_lun0")
err, _ := gadget.OverrideGadgetConfig("mass_storage_lun0", "file", imagePath)
if err != nil {
return fmt.Errorf("failed to get mass storage path: %w", err)
return fmt.Errorf("failed to set mass storage path: %w", err)
}
if err := writeFile(path.Join(massStorageFunctionPath, "file"), imagePath); err != nil {
return fmt.Errorf("failed to set image path: %w", err)
if err := gadget.UpdateGadgetConfig(usbgadget.UsbResetOnDemand); err != nil {
return fmt.Errorf("failed to update gadget config: %w", err)
}
return nil
}
@ -66,7 +64,7 @@ func setMassStorageMode(cdrom bool) error {
return nil
}
return gadget.UpdateGadgetConfig()
return gadget.UpdateGadgetConfig(usbgadget.UsbResetOnDemand)
}
func mountImage(imagePath string) error {