feat: release keyPress automatically

This commit is contained in:
Siyuan Miao 2025-09-11 13:05:20 +02:00
parent 72e3013337
commit 6ed633e380
2 changed files with 85 additions and 0 deletions

View File

@ -173,6 +173,50 @@ func (u *UsbGadget) SetOnKeysDownChange(f func(state KeysDownState)) {
u.onKeysDownChange = &f
}
const autoReleaseKeyboardInterval = time.Millisecond * 300
func (u *UsbGadget) scheduleAutoRelease(key byte) {
u.keysAutoReleaseLock.Lock()
defer u.keysAutoReleaseLock.Unlock()
if u.keysAutoReleaseTimer != nil {
u.keysAutoReleaseTimer.Stop()
}
u.keysAutoReleaseTimer = time.AfterFunc(autoReleaseKeyboardInterval, func() {
u.performAutoRelease(key)
})
}
func (u *UsbGadget) cancelAutoRelease() {
u.keysAutoReleaseLock.Lock()
defer u.keysAutoReleaseLock.Unlock()
if u.keysAutoReleaseTimer != nil {
u.keysAutoReleaseTimer.Stop()
}
}
func (u *UsbGadget) performAutoRelease(key byte) {
u.keysAutoReleaseLock.Lock()
defer u.keysAutoReleaseLock.Unlock()
select {
case <-u.keyboardStateCtx.Done():
return
default:
}
_, err := u.KeypressReport(key, false)
if err != nil {
u.log.Warn().Uint8("key", key).Msg("failed to auto-release keyboard key")
}
u.keysAutoReleaseTimer = nil
u.log.Trace().Uint8("key", key).Msg("auto release performed")
}
func (u *UsbGadget) listenKeyboardEvents() {
var path string
if u.keyboardHidFile != nil {
@ -398,5 +442,11 @@ func (u *UsbGadget) KeypressReport(key byte, press bool) (KeysDownState, error)
u.log.Warn().Uint8("modifier", modifier).Uints8("keys", keys).Msg("Could not write keypress report to hidg0")
}
if press {
u.scheduleAutoRelease(key)
} else {
u.cancelAutoRelease()
}
return u.UpdateKeysDown(modifier, keys), err
}

View File

@ -68,6 +68,9 @@ type UsbGadget struct {
keyboardState byte // keyboard latched state (NumLock, CapsLock, ScrollLock, Compose, Kana)
keysDownState KeysDownState // keyboard dynamic state (modifier keys and pressed keys)
keysAutoReleaseLock sync.Mutex
keysAutoReleaseTimer *time.Timer
keyboardStateLock sync.Mutex
keyboardStateCtx context.Context
keyboardStateCancel context.CancelFunc
@ -149,3 +152,35 @@ func newUsbGadget(name string, configMap map[string]gadgetConfigItem, enabledDev
return g
}
// Close cleans up resources used by the USB gadget
func (u *UsbGadget) Close() error {
// Cancel keyboard state context
if u.keyboardStateCancel != nil {
u.keyboardStateCancel()
}
// Stop auto-release timer
u.keysAutoReleaseLock.Lock()
if u.keysAutoReleaseTimer != nil {
u.keysAutoReleaseTimer.Stop()
u.keysAutoReleaseTimer = nil
}
u.keysAutoReleaseLock.Unlock()
// Close HID files
if u.keyboardHidFile != nil {
u.keyboardHidFile.Close()
u.keyboardHidFile = nil
}
if u.absMouseHidFile != nil {
u.absMouseHidFile.Close()
u.absMouseHidFile = nil
}
if u.relMouseHidFile != nil {
u.relMouseHidFile.Close()
u.relMouseHidFile = nil
}
return nil
}