mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-01-18 11:38:32 +01:00
* feat: release keyPress automatically * send keepalive when pressing the key * remove logging * clean up logging * chore: use unreliable channel to send keepalive events * chore: use ordered unreliable channel for pointer events * chore: adjust auto release key interval * chore: update logging for kbdAutoReleaseLock * chore: update comment for KEEPALIVE_INTERVAL * fix: should cancelAutorelease when pressed is true * fix: handshake won't happen if webrtc reconnects * chore: add trace log for writeWithTimeout * chore: add timeout for KeypressReport * chore: use the proper key to send release command * refactor: simplify HID RPC keyboard input handling and improve key state management - Updated `handleHidRPCKeyboardInput` to return errors directly instead of keys down state. - Refactored `rpcKeyboardReport` and `rpcKeypressReport` to return errors instead of states. - Introduced a queue for managing key down state updates in the `Session` struct to prevent input handling stalls. - Adjusted the `UpdateKeysDown` method to handle state changes more efficiently. - Removed unnecessary logging and commented-out code for clarity. * refactor: enhance keyboard auto-release functionality and key state management * fix: correct Windows default auto-repeat delay comment from 1ms to 1s * refactor: send keypress as early as possible * refactor: replace console.warn with console.info for HID RPC channel events * refactor: remove unused NewKeypressKeepAliveMessage function from HID RPC * fix: handle error in key release process and log warnings * fix: log warning on keypress report failure * fix: update auto-release keyboard interval to 225 * refactor: enhance keep-alive handling and jitter compensation in HID RPC - Implemented staleness guard to ignore outdated keep-alive packets. - Added jitter compensation logic to adjust timer extensions based on packet arrival times. - Introduced new methods for managing keep-alive state and reset functionality in the Session struct. - Updated auto-release delay mechanism to use dynamic durations based on keep-alive timing. - Adjusted keep-alive interval in the UI to improve responsiveness. * gofmt * clean up code * chore: use dynamic duration for scheduleAutoRelease * Use harcoded timer reset value for now * fix: prevent nil pointer dereference when stopping timers in Close method * refactor: remove nil check for kbdAutoReleaseTimers in DelayAutoReleaseWithDuration * refactor: optimize dependencies in useHidRpc hooks * refactor: streamline keep-alive timer management in useKeyboard hook * refactor: clarify comments in useKeyboard hook for resetKeyboardState function * refactor: reduce keysDownStateQueueSize * refactor: close and reset keysDownStateQueue in newSession function * chore: resolve conflicts * resolve conflicts --------- Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
124 lines
3.0 KiB
Go
124 lines
3.0 KiB
Go
package hidrpc
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/jetkvm/kvm/internal/usbgadget"
|
|
)
|
|
|
|
// MessageType is the type of the HID RPC message
|
|
type MessageType byte
|
|
|
|
const (
|
|
TypeHandshake MessageType = 0x01
|
|
TypeKeyboardReport MessageType = 0x02
|
|
TypePointerReport MessageType = 0x03
|
|
TypeWheelReport MessageType = 0x04
|
|
TypeKeypressReport MessageType = 0x05
|
|
TypeKeypressKeepAliveReport MessageType = 0x09
|
|
TypeMouseReport MessageType = 0x06
|
|
TypeKeyboardMacroReport MessageType = 0x07
|
|
TypeCancelKeyboardMacroReport MessageType = 0x08
|
|
TypeKeyboardLedState MessageType = 0x32
|
|
TypeKeydownState MessageType = 0x33
|
|
TypeKeyboardMacroState MessageType = 0x34
|
|
)
|
|
|
|
const (
|
|
Version byte = 0x01 // Version of the HID RPC protocol
|
|
)
|
|
|
|
// GetQueueIndex returns the index of the queue to which the message should be enqueued.
|
|
func GetQueueIndex(messageType MessageType) int {
|
|
switch messageType {
|
|
case TypeHandshake:
|
|
return 0
|
|
case TypeKeyboardReport, TypeKeypressReport, TypeKeyboardMacroReport, TypeKeyboardLedState, TypeKeydownState, TypeKeyboardMacroState:
|
|
return 1
|
|
case TypePointerReport, TypeMouseReport, TypeWheelReport:
|
|
return 2
|
|
// we don't want to block the queue for this message
|
|
case TypeCancelKeyboardMacroReport:
|
|
return 3
|
|
default:
|
|
return 3
|
|
}
|
|
}
|
|
|
|
// Unmarshal unmarshals the HID RPC message from the data.
|
|
func Unmarshal(data []byte, message *Message) error {
|
|
l := len(data)
|
|
if l < 1 {
|
|
return fmt.Errorf("invalid data length: %d", l)
|
|
}
|
|
|
|
message.t = MessageType(data[0])
|
|
message.d = data[1:]
|
|
return nil
|
|
}
|
|
|
|
// Marshal marshals the HID RPC message to the data.
|
|
func Marshal(message *Message) ([]byte, error) {
|
|
if message.t == 0 {
|
|
return nil, fmt.Errorf("invalid message type: %d", message.t)
|
|
}
|
|
|
|
data := make([]byte, len(message.d)+1)
|
|
data[0] = byte(message.t)
|
|
copy(data[1:], message.d)
|
|
|
|
return data, nil
|
|
}
|
|
|
|
// NewHandshakeMessage creates a new handshake message.
|
|
func NewHandshakeMessage() *Message {
|
|
return &Message{
|
|
t: TypeHandshake,
|
|
d: []byte{Version},
|
|
}
|
|
}
|
|
|
|
// NewKeyboardReportMessage creates a new keyboard report message.
|
|
func NewKeyboardReportMessage(keys []byte, modifier uint8) *Message {
|
|
return &Message{
|
|
t: TypeKeyboardReport,
|
|
d: append([]byte{modifier}, keys...),
|
|
}
|
|
}
|
|
|
|
// NewKeyboardLedMessage creates a new keyboard LED message.
|
|
func NewKeyboardLedMessage(state usbgadget.KeyboardState) *Message {
|
|
return &Message{
|
|
t: TypeKeyboardLedState,
|
|
d: []byte{state.Byte()},
|
|
}
|
|
}
|
|
|
|
// NewKeydownStateMessage creates a new keydown state message.
|
|
func NewKeydownStateMessage(state usbgadget.KeysDownState) *Message {
|
|
data := make([]byte, len(state.Keys)+1)
|
|
data[0] = state.Modifier
|
|
copy(data[1:], state.Keys)
|
|
|
|
return &Message{
|
|
t: TypeKeydownState,
|
|
d: data,
|
|
}
|
|
}
|
|
|
|
// NewKeyboardMacroStateMessage creates a new keyboard macro state message.
|
|
func NewKeyboardMacroStateMessage(state bool, isPaste bool) *Message {
|
|
data := make([]byte, 2)
|
|
if state {
|
|
data[0] = 1
|
|
}
|
|
if isPaste {
|
|
data[1] = 1
|
|
}
|
|
|
|
return &Message{
|
|
t: TypeKeyboardMacroState,
|
|
d: data,
|
|
}
|
|
}
|