Update App version to 0.0.4

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
This commit is contained in:
luckfox-eng29
2025-11-11 20:38:22 +08:00
parent 4e82b8a11c
commit 5e17c52afc
41 changed files with 3537 additions and 598 deletions

109
usb.go
View File

@@ -1,6 +1,7 @@
package kvm
import (
"fmt"
"os"
"time"
@@ -43,6 +44,21 @@ func initUsbGadget() {
}
})
// Set callback for HID device missing errors
gadget.SetOnHidDeviceMissing(func(device string, err error) {
usbLogger.Error().
Str("device", device).
Err(err).
Msg("HID device missing, sending notification to client")
if currentSession != nil {
writeJSONRPCEvent("hidDeviceMissing", map[string]interface{}{
"device": device,
"error": err.Error(),
}, currentSession)
}
})
// open the keyboard hid file to listen for keyboard events
if err := gadget.OpenKeyboardHidFile(); err != nil {
usbLogger.Error().Err(err).Msg("failed to open keyboard hid file")
@@ -136,3 +152,96 @@ func rpcSendUsbWakeupSignal() error {
}
return nil
}
// rpcReinitializeUsbGadget reinitializes the USB gadget
func rpcReinitializeUsbGadget() error {
usbLogger.Info().Msg("reinitializing USB gadget (hard)")
if gadget == nil {
return fmt.Errorf("USB gadget not initialized")
}
mediaState, _ := rpcGetVirtualMediaState()
if mediaState != nil && (mediaState.Filename != "" || mediaState.URL != "") {
usbLogger.Info().Interface("mediaState", mediaState).Msg("virtual media mounted, unmounting before USB reinit")
if err := rpcUnmountImage(); err != nil {
usbLogger.Warn().Err(err).Msg("failed to unmount virtual media before USB reinit")
}
}
// Recreate the gadget instance similar to program restart
gadget = usbgadget.NewUsbGadget(
"kvm",
config.UsbDevices,
config.UsbConfig,
usbLogger,
)
// Reapply callbacks
gadget.SetOnKeyboardStateChange(func(state usbgadget.KeyboardState) {
if currentSession != nil {
writeJSONRPCEvent("keyboardLedState", state, currentSession)
}
})
gadget.SetOnHidDeviceMissing(func(device string, err error) {
usbLogger.Error().
Str("device", device).
Err(err).
Msg("HID device missing, sending notification to client")
if currentSession != nil {
writeJSONRPCEvent("hidDeviceMissing", map[string]interface{}{
"device": device,
"error": err.Error(),
}, currentSession)
}
})
// Reopen keyboard HID file
if err := gadget.OpenKeyboardHidFile(); err != nil {
usbLogger.Warn().Err(err).Msg("failed to open keyboard hid file after reinit")
}
// Force a USB state update notification
triggerUSBStateUpdate()
initSystemInfo()
usbLogger.Info().Msg("USB gadget reinitialized successfully")
return nil
}
// rpcReinitializeUsbGadgetSoft performs a lightweight refresh:
// reapply configuration and rebind without recreating the gadget instance.
func rpcReinitializeUsbGadgetSoft() error {
usbLogger.Info().Msg("reinitializing USB gadget (soft)")
if gadget == nil {
return fmt.Errorf("USB gadget not initialized")
}
mediaState, _ := rpcGetVirtualMediaState()
if mediaState != nil && (mediaState.Filename != "" || mediaState.URL != "") {
usbLogger.Info().Interface("mediaState", mediaState).Msg("virtual media mounted, unmounting before USB soft reinit")
if err := rpcUnmountImage(); err != nil {
usbLogger.Warn().Err(err).Msg("failed to unmount virtual media before USB soft reinit")
}
}
// Update gadget configuration (will rebind USB inside)
if err := gadget.UpdateGadgetConfig(); err != nil {
usbLogger.Error().Err(err).Msg("failed to soft reinitialize USB gadget")
return fmt.Errorf("failed to soft reinitialize USB gadget: %w", err)
}
// Reopen keyboard HID file
if err := gadget.OpenKeyboardHidFile(); err != nil {
usbLogger.Warn().Err(err).Msg("failed to reopen keyboard hid file after soft reinit")
}
// Force a USB state update notification
triggerUSBStateUpdate()
usbLogger.Info().Msg("USB gadget soft reinitialized successfully")
return nil
}