mirror of https://github.com/jetkvm/kvm.git
Compare commits
2 Commits
e5f58332b7
...
4b9b0a64e9
Author | SHA1 | Date |
---|---|---|
|
4b9b0a64e9 | |
|
0dd7098821 |
|
@ -100,7 +100,7 @@ func getKeyboardState(b byte) KeyboardState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) updateKeyboardState(state byte) {
|
func (u *UsbGadget) updateKeyboardState(state uint8) {
|
||||||
u.keyboardStateLock.Lock()
|
u.keyboardStateLock.Lock()
|
||||||
defer u.keyboardStateLock.Unlock()
|
defer u.keyboardStateLock.Unlock()
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ func (u *UsbGadget) listenKeyboardEvents() {
|
||||||
l.Trace().Msg("starting")
|
l.Trace().Msg("starting")
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
buf := make([]byte, hidReadBufferSize)
|
buf := make([]uint8, hidReadBufferSize)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-u.keyboardStateCtx.Done():
|
case <-u.keyboardStateCtx.Done():
|
||||||
|
@ -245,12 +245,12 @@ func (u *UsbGadget) OpenKeyboardHidFile() error {
|
||||||
return u.openKeyboardHidFile()
|
return u.openKeyboardHidFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) keyboardWriteHidFile(modifier byte, keys []byte) error {
|
func (u *UsbGadget) keyboardWriteHidFile(modifier uint8, keys []uint8) error {
|
||||||
if err := u.openKeyboardHidFile(); err != nil {
|
if err := u.openKeyboardHidFile(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := u.keyboardHidFile.Write(append([]byte{modifier, 0x00}, keys[:hidKeyBufferSize]...))
|
_, err := u.keyboardHidFile.Write(append([]uint8{modifier, 0x00}, keys[:hidKeyBufferSize]...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
u.logWithSuppression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0")
|
u.logWithSuppression("keyboardWriteHidFile", 100, u.log, err, "failed to write to hidg0")
|
||||||
u.keyboardHidFile.Close()
|
u.keyboardHidFile.Close()
|
||||||
|
@ -261,7 +261,7 @@ func (u *UsbGadget) keyboardWriteHidFile(modifier byte, keys []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) KeyboardReport(modifier byte, keys []byte) error {
|
func (u *UsbGadget) KeyboardReport(modifier uint8, keys []uint8) error {
|
||||||
u.keyboardLock.Lock()
|
u.keyboardLock.Lock()
|
||||||
defer u.keyboardLock.Unlock()
|
defer u.keyboardLock.Unlock()
|
||||||
defer u.resetUserInputTime()
|
defer u.resetUserInputTime()
|
||||||
|
@ -270,7 +270,7 @@ func (u *UsbGadget) KeyboardReport(modifier byte, keys []byte) error {
|
||||||
keys = keys[:hidKeyBufferSize]
|
keys = keys[:hidKeyBufferSize]
|
||||||
}
|
}
|
||||||
if len(keys) < hidKeyBufferSize {
|
if len(keys) < hidKeyBufferSize {
|
||||||
keys = append(keys, make([]byte, hidKeyBufferSize-len(keys))...)
|
keys = append(keys, make([]uint8, hidKeyBufferSize-len(keys))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return u.keyboardWriteHidFile(modifier, keys)
|
return u.keyboardWriteHidFile(modifier, keys)
|
||||||
|
@ -290,7 +290,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyCodeToMaskMap is a slice of KeyCodeMask for quick lookup
|
// KeyCodeToMaskMap is a slice of KeyCodeMask for quick lookup
|
||||||
var KeyCodeToMaskMap = map[byte]byte{
|
var KeyCodeToMaskMap = map[uint8]uint8{
|
||||||
LeftControl: ModifierMaskLeftControl,
|
LeftControl: ModifierMaskLeftControl,
|
||||||
LeftShift: ModifierMaskLeftShift,
|
LeftShift: ModifierMaskLeftShift,
|
||||||
LeftAlt: ModifierMaskLeftAlt,
|
LeftAlt: ModifierMaskLeftAlt,
|
||||||
|
@ -301,14 +301,14 @@ var KeyCodeToMaskMap = map[byte]byte{
|
||||||
RightSuper: ModifierMaskRightSuper,
|
RightSuper: ModifierMaskRightSuper,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) KeypressReport(key byte, press bool) (KeysDownState, error) {
|
func (u *UsbGadget) KeypressReport(key uint8, press bool) (KeysDownState, error) {
|
||||||
u.keyboardLock.Lock()
|
u.keyboardLock.Lock()
|
||||||
defer u.keyboardLock.Unlock()
|
defer u.keyboardLock.Unlock()
|
||||||
defer u.resetUserInputTime()
|
defer u.resetUserInputTime()
|
||||||
|
|
||||||
var state = u.keysDownState
|
var state = u.keysDownState
|
||||||
modifier := state.Modifier
|
modifier := state.Modifier
|
||||||
keys := append([]byte(nil), state.Keys...)
|
keys := state.Keys[:]
|
||||||
|
|
||||||
if mask, exists := KeyCodeToMaskMap[key]; exists {
|
if mask, exists := KeyCodeToMaskMap[key]; exists {
|
||||||
// If the key is a modifier key, we update the keyboardModifier state
|
// If the key is a modifier key, we update the keyboardModifier state
|
||||||
|
@ -361,12 +361,10 @@ 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")
|
u.log.Warn().Uint8("modifier", modifier).Uints8("keys", keys).Msg("Could not write keypress report to hidg0")
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = KeysDownState{
|
state.Modifier = modifier
|
||||||
Modifier: modifier,
|
state.Keys = keys
|
||||||
Keys: []byte(keys[:]),
|
|
||||||
}
|
|
||||||
|
|
||||||
u.updateKeyDownState(result)
|
u.updateKeyDownState(state)
|
||||||
|
|
||||||
return result, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,17 +85,17 @@ func (u *UsbGadget) absMouseWriteHidFile(data []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) AbsMouseReport(x int, y int, buttons uint8) error {
|
func (u *UsbGadget) AbsMouseReport(x, y int, buttons uint8) error {
|
||||||
u.absMouseLock.Lock()
|
u.absMouseLock.Lock()
|
||||||
defer u.absMouseLock.Unlock()
|
defer u.absMouseLock.Unlock()
|
||||||
|
|
||||||
err := u.absMouseWriteHidFile([]byte{
|
err := u.absMouseWriteHidFile([]byte{
|
||||||
1, // Report ID 1
|
1, // Report ID 1
|
||||||
buttons, // Buttons
|
buttons, // Buttons
|
||||||
byte(x), // X Low Byte
|
uint8(x), // X Low Byte
|
||||||
byte(x >> 8), // X High Byte
|
uint8(x >> 8), // X High Byte
|
||||||
byte(y), // Y Low Byte
|
uint8(y), // Y Low Byte
|
||||||
byte(y >> 8), // Y High Byte
|
uint8(y >> 8), // Y High Byte
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -75,15 +75,15 @@ func (u *UsbGadget) relMouseWriteHidFile(data []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UsbGadget) RelMouseReport(mx int8, my int8, buttons uint8) error {
|
func (u *UsbGadget) RelMouseReport(mx, my int8, buttons uint8) error {
|
||||||
u.relMouseLock.Lock()
|
u.relMouseLock.Lock()
|
||||||
defer u.relMouseLock.Unlock()
|
defer u.relMouseLock.Unlock()
|
||||||
|
|
||||||
err := u.relMouseWriteHidFile([]byte{
|
err := u.relMouseWriteHidFile([]byte{
|
||||||
buttons, // Buttons
|
buttons, // Buttons
|
||||||
byte(mx), // X
|
uint8(mx), // X
|
||||||
byte(my), // Y
|
uint8(my), // Y
|
||||||
0, // Wheel
|
0, // Wheel
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -42,8 +42,8 @@ var defaultUsbGadgetDevices = Devices{
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeysDownState struct {
|
type KeysDownState struct {
|
||||||
Modifier byte `json:"modifier"`
|
Modifier uint8 `json:"modifier"`
|
||||||
Keys ByteSlice `json:"keys"`
|
Keys []uint8 `json:"keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsbGadget is a struct that represents a USB gadget.
|
// UsbGadget is a struct that represents a USB gadget.
|
||||||
|
@ -65,7 +65,7 @@ type UsbGadget struct {
|
||||||
relMouseHidFile *os.File
|
relMouseHidFile *os.File
|
||||||
relMouseLock sync.Mutex
|
relMouseLock sync.Mutex
|
||||||
|
|
||||||
keyboardState byte // keyboard latched state (NumLock, CapsLock, ScrollLock, Compose, Kana)
|
keyboardState uint8 // keyboard latched state (NumLock, CapsLock, ScrollLock, Compose, Kana)
|
||||||
keysDownState KeysDownState // keyboard dynamic state (modifier keys and pressed keys)
|
keysDownState KeysDownState // keyboard dynamic state (modifier keys and pressed keys)
|
||||||
|
|
||||||
keyboardStateLock sync.Mutex
|
keyboardStateLock sync.Mutex
|
||||||
|
@ -131,7 +131,7 @@ func newUsbGadget(name string, configMap map[string]gadgetConfigItem, enabledDev
|
||||||
keyboardStateCtx: keyboardCtx,
|
keyboardStateCtx: keyboardCtx,
|
||||||
keyboardStateCancel: keyboardCancel,
|
keyboardStateCancel: keyboardCancel,
|
||||||
keyboardState: 0,
|
keyboardState: 0,
|
||||||
keysDownState: KeysDownState{Modifier: 0, Keys: []byte{0, 0, 0, 0, 0, 0}}, // must be initialized to hidKeyBufferSize (6) zero bytes
|
keysDownState: KeysDownState{Modifier: 0, Keys: []uint8{0, 0, 0, 0, 0, 0}}, // must be initialized to hidKeyBufferSize (6) zero bytes
|
||||||
enabledDevices: *enabledDevices,
|
enabledDevices: *enabledDevices,
|
||||||
lastUserInput: time.Now(),
|
lastUserInput: time.Now(),
|
||||||
log: logger,
|
log: logger,
|
||||||
|
|
|
@ -2,7 +2,6 @@ package usbgadget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -11,31 +10,6 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ByteSlice []byte
|
|
||||||
|
|
||||||
func (s ByteSlice) MarshalJSON() ([]byte, error) {
|
|
||||||
vals := make([]int, len(s))
|
|
||||||
for i, v := range s {
|
|
||||||
vals[i] = int(v)
|
|
||||||
}
|
|
||||||
return json.Marshal(vals)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ByteSlice) UnmarshalJSON(data []byte) error {
|
|
||||||
var vals []int
|
|
||||||
if err := json.Unmarshal(data, &vals); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*s = make([]byte, len(vals))
|
|
||||||
for i, v := range vals {
|
|
||||||
if v < 0 || v > 255 {
|
|
||||||
return fmt.Errorf("value %d out of byte range", v)
|
|
||||||
}
|
|
||||||
(*s)[i] = byte(v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func joinPath(basePath string, paths []string) string {
|
func joinPath(basePath string, paths []string) string {
|
||||||
pathArr := append([]string{basePath}, paths...)
|
pathArr := append([]string{basePath}, paths...)
|
||||||
return filepath.Join(pathArr...)
|
return filepath.Join(pathArr...)
|
||||||
|
|
|
@ -566,7 +566,7 @@ func riskyCallRPCHandler(logger zerolog.Logger, handler RPCHandler, params map[s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Trace().Msg("Calling RPC handler")
|
logger.Trace().Interface("args", args).Msg("Calling RPC handler")
|
||||||
results := handlerValue.Call(args)
|
results := handlerValue.Call(args)
|
||||||
|
|
||||||
if len(results) == 0 {
|
if len(results) == 0 {
|
||||||
|
|
|
@ -11,14 +11,10 @@ import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||||
import { cx } from "@/cva.config";
|
import { cx } from "@/cva.config";
|
||||||
import { keys } from "@/keyboardMappings";
|
import { keys } from "@/keyboardMappings";
|
||||||
import {
|
import {
|
||||||
MouseState,
|
|
||||||
RTCState,
|
|
||||||
SettingsState,
|
|
||||||
useMouseStore,
|
useMouseStore,
|
||||||
useRTCStore,
|
useRTCStore,
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
useVideoStore,
|
useVideoStore,
|
||||||
VideoState,
|
|
||||||
} from "@/hooks/stores";
|
} from "@/hooks/stores";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -31,15 +27,15 @@ import {
|
||||||
export default function WebRTCVideo() {
|
export default function WebRTCVideo() {
|
||||||
// Video and stream related refs and states
|
// Video and stream related refs and states
|
||||||
const videoElm = useRef<HTMLVideoElement>(null);
|
const videoElm = useRef<HTMLVideoElement>(null);
|
||||||
const mediaStream = useRTCStore((state: RTCState) => state.mediaStream);
|
const mediaStream = useRTCStore(state => state.mediaStream);
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
const peerConnectionState = useRTCStore((state: RTCState) => state.peerConnectionState);
|
const peerConnectionState = useRTCStore(state => state.peerConnectionState);
|
||||||
const [isPointerLockActive, setIsPointerLockActive] = useState(false);
|
const [isPointerLockActive, setIsPointerLockActive] = useState(false);
|
||||||
// Store hooks
|
// Store hooks
|
||||||
const settings = useSettingsStore();
|
const settings = useSettingsStore();
|
||||||
const { sendKeypressEvent, resetKeyboardState } = useKeyboard();
|
const { sendKeypressEvent, resetKeyboardState } = useKeyboard();
|
||||||
const setMousePosition = useMouseStore((state: MouseState) => state.setMousePosition);
|
const setMousePosition = useMouseStore(state => state.setMousePosition);
|
||||||
const setMouseMove = useMouseStore((state: MouseState) => state.setMouseMove);
|
const setMouseMove = useMouseStore(state => state.setMouseMove);
|
||||||
const {
|
const {
|
||||||
setClientSize: setVideoClientSize,
|
setClientSize: setVideoClientSize,
|
||||||
setSize: setVideoSize,
|
setSize: setVideoSize,
|
||||||
|
@ -50,15 +46,15 @@ export default function WebRTCVideo() {
|
||||||
} = useVideoStore();
|
} = useVideoStore();
|
||||||
|
|
||||||
// Video enhancement settings
|
// Video enhancement settings
|
||||||
const videoSaturation = useSettingsStore((state: SettingsState) => state.videoSaturation);
|
const videoSaturation = useSettingsStore(state => state.videoSaturation);
|
||||||
const videoBrightness = useSettingsStore((state: SettingsState) => state.videoBrightness);
|
const videoBrightness = useSettingsStore(state => state.videoBrightness);
|
||||||
const videoContrast = useSettingsStore((state: SettingsState) => state.videoContrast);
|
const videoContrast = useSettingsStore(state => state.videoContrast);
|
||||||
|
|
||||||
// RTC related states
|
// RTC related states
|
||||||
const peerConnection = useRTCStore((state: RTCState ) => state.peerConnection);
|
const peerConnection = useRTCStore(state => state.peerConnection);
|
||||||
|
|
||||||
// HDMI and UI states
|
// HDMI and UI states
|
||||||
const hdmiState = useVideoStore((state: VideoState) => state.hdmiState);
|
const hdmiState = useVideoStore(state => state.hdmiState);
|
||||||
const hdmiError = ["no_lock", "no_signal", "out_of_range"].includes(hdmiState);
|
const hdmiError = ["no_lock", "no_signal", "out_of_range"].includes(hdmiState);
|
||||||
const isVideoLoading = !isPlaying;
|
const isVideoLoading = !isPlaying;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,9 @@ export default function useKeyboard() {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to send keypress:", resp.error);
|
console.error("Failed to send keypress:", resp.error);
|
||||||
} else {
|
} else {
|
||||||
|
console.log(resp);
|
||||||
const keyDownState = resp.result as KeysDownState;
|
const keyDownState = resp.result as KeysDownState;
|
||||||
|
console.log("Key Down State:", keyDownState);
|
||||||
// We do this for the info bar to display the currently pressed keys for the user
|
// We do this for the info bar to display the currently pressed keys for the user
|
||||||
setKeysDownState(keyDownState);
|
setKeysDownState(keyDownState);
|
||||||
}
|
}
|
||||||
|
|
|
@ -661,7 +661,7 @@ export default function KvmIdRoute() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rpcDataChannel?.readyState !== "open") return;
|
if (rpcDataChannel?.readyState !== "open") return;
|
||||||
send("getVideoState", {}, (resp: JsonRpcResponse) => {
|
send("getVideoState", {}, resp => {
|
||||||
if ("error" in resp) return;
|
if ("error" in resp) return;
|
||||||
setHdmiState(resp.result as Parameters<VideoState["setHdmiState"]>[0]);
|
setHdmiState(resp.result as Parameters<VideoState["setHdmiState"]>[0]);
|
||||||
});
|
});
|
||||||
|
@ -673,7 +673,7 @@ export default function KvmIdRoute() {
|
||||||
if (keyboardLedState !== undefined) return;
|
if (keyboardLedState !== undefined) return;
|
||||||
console.log("Requesting keyboard led state");
|
console.log("Requesting keyboard led state");
|
||||||
|
|
||||||
send("getKeyboardLedState", {}, (resp: JsonRpcResponse) => {
|
send("getKeyboardLedState", {}, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to get keyboard led state", resp.error);
|
console.error("Failed to get keyboard led state", resp.error);
|
||||||
return;
|
return;
|
||||||
|
@ -689,7 +689,7 @@ export default function KvmIdRoute() {
|
||||||
if (keysDownState !== undefined) return;
|
if (keysDownState !== undefined) return;
|
||||||
console.log("Requesting keys down state");
|
console.log("Requesting keys down state");
|
||||||
|
|
||||||
send("getKeyDownState", {}, (resp: JsonRpcResponse) => {
|
send("getKeyDownState", {}, resp => {
|
||||||
if ("error" in resp) {
|
if ("error" in resp) {
|
||||||
console.error("Failed to get key down state", resp.error);
|
console.error("Failed to get key down state", resp.error);
|
||||||
return;
|
return;
|
||||||
|
|
8
usb.go
8
usb.go
|
@ -43,19 +43,19 @@ func initUsbGadget() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcKeyboardReport(modifier byte, keys []byte) error {
|
func rpcKeyboardReport(modifier uint8, keys []uint8) error {
|
||||||
return gadget.KeyboardReport(modifier, keys)
|
return gadget.KeyboardReport(modifier, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcKeypressReport(key byte, press bool) (usbgadget.KeysDownState, error) {
|
func rpcKeypressReport(key uint8, press bool) (usbgadget.KeysDownState, error) {
|
||||||
return gadget.KeypressReport(key, press)
|
return gadget.KeypressReport(key, press)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcAbsMouseReport(x int, y int, buttons uint8) error {
|
func rpcAbsMouseReport(x, y int, buttons uint8) error {
|
||||||
return gadget.AbsMouseReport(x, y, buttons)
|
return gadget.AbsMouseReport(x, y, buttons)
|
||||||
}
|
}
|
||||||
|
|
||||||
func rpcRelMouseReport(dx int8, dy int8, buttons uint8) error {
|
func rpcRelMouseReport(dx, dy int8, buttons uint8) error {
|
||||||
return gadget.RelMouseReport(dx, dy, buttons)
|
return gadget.RelMouseReport(dx, dy, buttons)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue