Documentation
¶
Overview ¶
Package input implements JetKVM HID-RPC encoding and bounded input execution.
Index ¶
- Constants
- Variables
- func CompileKeyCombo(names []string) (modifier byte, keys []byte, err error)
- func Handshake() []byte
- func KeyboardReport(modifier byte, keys ...byte) ([]byte, error)
- func KeypressReport(key byte, pressed bool) ([]byte, error)
- func ParseHandshake(data []byte) (byte, error)
- func PointerReport(x, y int, buttons ButtonMask) ([]byte, error)
- func RelativeMouseReport(dx, dy int, buttons ButtonMask) ([]byte, error)
- type Action
- type ActionReceipt
- type ActionStatus
- type ActionType
- type Batch
- type BatchReceipt
- type BatchStatus
- type Button
- type ButtonMask
- type GenerationToken
- type HIDTransport
- type Keystroke
- type Lease
- type Limits
- type Manager
- func (m *Manager) Acquire(expectedGeneration uint64) (*Lease, error)
- func (m *Manager) AdvanceGeneration(ctx context.Context, next uint64) error
- func (m *Manager) Fence(expectedGeneration uint64) error
- func (m *Manager) Generation() uint64
- func (m *Manager) Reconcile(ctx context.Context, expectedGeneration uint64) error
- func (m *Manager) RunActions(ctx context.Context, expectedGeneration uint64, batch Batch) (BatchReceipt, error)
- func (m *Manager) State() State
- type ManagerConfig
- type Observation
- type ObservationBinding
- type Point
- type Reliability
- type ScreenshotObserver
- type State
Constants ¶
const ( MaxKeyHoldDuration = 12 * time.Second MaxActions = 16 MaxBatchDuration = 15 * time.Second MaxWaitDuration = 5 * time.Second MaxTotalWait = 10 * time.Second )
const (
HIDRPCVersion byte = 0x01
)
HID-RPC v1 message types observed in the JetKVM 0.5.8/dev protocol.
const MaxTextRunes = 4096
Variables ¶
var ( ErrInvalidAction = errors.New("invalid input action") ErrObservationStale = errors.New("bound observation is stale") )
var ( ErrUnknownKey = errors.New("unknown key") ErrUnsupportedText = errors.New("text contains a character unsupported by the US keyboard layout") )
var ( ErrLeaseBusy = errors.New("input lease is already held") ErrStaleGeneration = errors.New("input generation is stale") ErrLeaseReleased = errors.New("input lease is released") ErrInputUncertain = errors.New("input state is uncertain") ErrNeutralization = errors.New("input neutralization could not be confirmed") ErrObservationMissing = errors.New("screenshot observer is unavailable") )
var ErrInvalidProtocolValue = errors.New("invalid HID protocol value")
Functions ¶
func CompileKeyCombo ¶
CompileKeyCombo resolves a named chord to a complete keyboard report. Names are case-insensitive and ignore '-', '_', and spaces.
func KeyboardReport ¶
KeyboardReport marshals one complete boot-keyboard state. Unused slots are zeroed.
func KeypressReport ¶
KeypressReport marshals a single key transition.
func ParseHandshake ¶
ParseHandshake validates a device handshake and returns its negotiated version.
func PointerReport ¶
func PointerReport(x, y int, buttons ButtonMask) ([]byte, error)
PointerReport marshals absolute coordinates in JetKVM's 0..32767 HID space.
func RelativeMouseReport ¶
func RelativeMouseReport(dx, dy int, buttons ButtonMask) ([]byte, error)
RelativeMouseReport marshals one relative pointer update.
Types ¶
type Action ¶
type Action struct {
Type ActionType `json:"type"`
X int `json:"x,omitzero"`
Y int `json:"y,omitzero"`
Button Button `json:"button,omitempty"`
Path []Point `json:"path,omitempty"`
DeltaX int `json:"delta_x,omitzero"`
DeltaY int `json:"delta_y,omitzero"`
Keys []string `json:"keys,omitempty"`
Text string `json:"text,omitempty"`
Duration time.Duration `json:"duration,omitzero"`
}
Action is a closed union. Validate rejects fields that do not belong to Type.
type ActionReceipt ¶
type ActionReceipt struct {
Index int `json:"index"`
Type ActionType `json:"type"`
Status ActionStatus `json:"status"`
Error string `json:"error,omitzero"`
}
type ActionStatus ¶
type ActionStatus string
const ( ActionNotStarted ActionStatus = "not_started" ActionSendStarted ActionStatus = "send_started" ActionAccepted ActionStatus = "accepted" ActionFailed ActionStatus = "failed" ActionAmbiguous ActionStatus = "ambiguous" )
type ActionType ¶
type ActionType string
const ( ActionMove ActionType = "move" ActionClick ActionType = "click" ActionDoubleClick ActionType = "double_click" ActionDrag ActionType = "drag" ActionScroll ActionType = "scroll" ActionKeypress ActionType = "keypress" ActionKeyHold ActionType = "key_hold" ActionTypeText ActionType = "type" ActionWait ActionType = "wait" ActionScreenshot ActionType = "screenshot" )
type Batch ¶
type Batch struct {
Observation *ObservationBinding
Actions []Action
}
type BatchReceipt ¶
type BatchReceipt struct {
Generation uint64 `json:"generation"`
Status BatchStatus `json:"status"`
Actions []ActionReceipt `json:"actions"`
Observation Observation `json:"observation,omitzero"`
Neutralized bool `json:"neutralized"`
CleanupFailure string `json:"cleanup_failure,omitzero"`
}
type BatchStatus ¶
type BatchStatus string
const ( BatchAccepted BatchStatus = "accepted" BatchPartial BatchStatus = "partial" BatchFailed BatchStatus = "failed" BatchAmbiguous BatchStatus = "ambiguous" )
type ButtonMask ¶
type ButtonMask byte
type GenerationToken ¶
type GenerationToken struct {
// contains filtered or unexported fields
}
GenerationToken binds every input operation to one control generation and one exclusive lease. Its opaque nonce prevents a stale caller from reusing another lease in the same generation.
func (GenerationToken) Generation ¶
func (t GenerationToken) Generation() uint64
type HIDTransport ¶
type HIDTransport interface {
SendHID(context.Context, uint64, Reliability, []byte) error
SendWheel(context.Context, uint64, int8, int8) error
Flush(context.Context, uint64) error
}
HIDTransport is the device actor's narrow input transport. SendHID carries HID-RPC v1 frames. SendWheel is separate because JetKVM 0.5.8/dev exposes wheelReport through JSON-RPC rather than handling HID-RPC message 0x04. Implementations must fence generation at their final send boundary.
type Keystroke ¶
func CompileText ¶
CompileText completely validates and translates printable US-layout text. It returns no partial result when any rune is unsupported.
type Lease ¶
type Lease struct {
// contains filtered or unexported fields
}
func (*Lease) RunActions ¶
func (*Lease) Token ¶
func (l *Lease) Token() GenerationToken
type Limits ¶
type Limits struct {
KeyHold time.Duration
InterKey time.Duration
DoubleClickDelay time.Duration
MaxActions int
MaxBatchDuration time.Duration
MaxWaitDuration time.Duration
MaxTotalWait time.Duration
MaxObservationAge time.Duration
}
func DefaultLimits ¶
func DefaultLimits() Limits
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func NewManager ¶
func NewManager(cfg ManagerConfig) (*Manager, error)
func (*Manager) AdvanceGeneration ¶
AdvanceGeneration neutralizes the old session before publishing a newer generation. A failure leaves the old generation fenced as uncertain.
func (*Manager) Fence ¶
Fence immediately rejects further sends from the current generation. It is used when the device actor observes a disconnect or session replacement. The uncertain latch remains set even if the lease later neutralizes cleanly; callers must reconnect and Reconcile before accepting more input.
func (*Manager) Generation ¶
func (*Manager) Reconcile ¶
Reconcile sends authoritative neutral state and clears an uncertain latch. It is the only path that may make an uncertain manager ready again.
func (*Manager) RunActions ¶
func (m *Manager) RunActions(ctx context.Context, expectedGeneration uint64, batch Batch) (BatchReceipt, error)
RunActions acquires a single-use exclusive lease, executes the prevalidated batch, and always attempts input neutralization before returning.
type ManagerConfig ¶
type ManagerConfig struct {
Transport HIDTransport
Observer ScreenshotObserver
Generation uint64
Limits Limits
CleanupTimeout time.Duration
Random io.Reader
Now func() time.Time
}
type Observation ¶
type ObservationBinding ¶
type ObservationBinding struct {
ID string
Generation uint64
Width int
Height int
CapturedAt time.Time
}
ObservationBinding ties pixel coordinates to one fresh video frame and control generation. Coordinate actions are rejected without this binding.
type ScreenshotObserver ¶
type ScreenshotObserver interface {
Capture(context.Context, uint64) (Observation, error)
}