diff --git a/common/include/common/KVMFR.h b/common/include/common/KVMFR.h index 4a2deb29..1399a849 100644 --- a/common/include/common/KVMFR.h +++ b/common/include/common/KVMFR.h @@ -28,9 +28,10 @@ #include #include "types.h" #include "LGMPConfig.h" +#include "KVMFRInput.h" #define KVMFR_MAGIC "KVMFR---" -#define KVMFR_VERSION 29 +#define KVMFR_VERSION 30 // Fallback used by producers that cannot report the source display's SDR // white level. IDD frames override this with IDDCX_METADATA2::SdrWhiteLevel. @@ -61,7 +62,8 @@ enum { KVMFR_FEATURE_SETCURSORPOS = 0x1, KVMFR_FEATURE_WINDOWSIZE = 0x2, - KVMFR_FEATURE_FRAME_SCHEDULE = 0x4 + KVMFR_FEATURE_FRAME_SCHEDULE = 0x4, + KVMFR_FEATURE_INPUT = 0x8 }; typedef uint32_t KVMFRFeatureFlags; diff --git a/common/include/common/KVMFRInput.h b/common/include/common/KVMFRInput.h new file mode 100644 index 00000000..7f660cb6 --- /dev/null +++ b/common/include/common/KVMFRInput.h @@ -0,0 +1,170 @@ +/** + * Looking Glass + * Copyright © 2017-2026 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _H_LG_COMMON_KVMFR_INPUT_ +#define _H_LG_COMMON_KVMFR_INPUT_ + +#pragma once + +#include +#include + +#define KVMFR_INPUT_VERSION 1 +#define KVMFR_INPUT_MOUSE_BUTTON_COUNT 32 +#define KVMFR_INPUT_MOUSE_ABSOLUTE_MAX 32767 +#define KVMFR_INPUT_KEYBOARD_KEY_COUNT 6 +#define KVMFR_INPUT_KEYBOARD_USAGE_MAX 0xe7 + +typedef uint32_t KVMFRInputMouseButtons; + +/* + * Bits 0..31 correspond to USB HID mouse button usages 1..32. Wheel motion + * is carried separately and must not be represented as a button. + */ +typedef struct KVMFRInputMouseRelative +{ + KVMFRInputMouseButtons buttons; + int32_t deltaX; + int32_t deltaY; + int32_t wheel; +} +KVMFRInputMouseRelative; + +typedef struct KVMFRInputMouseAbsolute +{ + KVMFRInputMouseButtons buttons; + uint16_t x; + uint16_t y; + int32_t wheel; + uint32_t reserved; +} +KVMFRInputMouseAbsolute; + +typedef struct KVMFRInputKeyboard +{ + uint8_t modifiers; + uint8_t keys[KVMFR_INPUT_KEYBOARD_KEY_COUNT]; + uint8_t reserved[9]; +} +KVMFRInputKeyboard; + +typedef union KVMFRInputPayload +{ + KVMFRInputMouseRelative mouseRelative; + KVMFRInputMouseAbsolute mouseAbsolute; + KVMFRInputKeyboard keyboard; + uint8_t reserved[16]; +} +KVMFRInputPayload; + +enum +{ + KVMFR_INPUT_MESSAGE_CLAIM = 1, + KVMFR_INPUT_MESSAGE_RELEASE = 2, + KVMFR_INPUT_MESSAGE_KEEPALIVE = 3, + KVMFR_INPUT_MESSAGE_RESET = 4, + KVMFR_INPUT_MESSAGE_MOUSE_RELATIVE = 5, + KVMFR_INPUT_MESSAGE_MOUSE_ABSOLUTE = 6, + KVMFR_INPUT_MESSAGE_KEYBOARD = 7 +}; + +typedef uint32_t KVMFRInputMessageType; + +typedef struct KVMFRInputMessage +{ + KVMFRInputMessageType type; + // Non-zero client input activation generation. + uint32_t generation; + // Non-zero ordered sequence within generation, beginning at one. + uint32_t sequence; + // Must be zero. + uint32_t reserved; + KVMFRInputPayload payload; +} +KVMFRInputMessage; + +enum +{ + KVMFR_INPUT_CAP_MOUSE_RELATIVE = 0x1, + KVMFR_INPUT_CAP_MOUSE_ABSOLUTE = 0x2, + KVMFR_INPUT_CAP_KEYBOARD = 0x4 +}; + +typedef uint32_t KVMFRInputCapabilityFlags; + +enum +{ + KVMFR_INPUT_STATUS_AVAILABLE = 0x1, + KVMFR_INPUT_STATUS_HAS_OWNER = 0x2, +}; + +typedef uint32_t KVMFRInputStatusFlags; + +typedef struct KVMFRInputStatus +{ + uint32_t version; + KVMFRInputCapabilityFlags capabilities; + KVMFRInputStatusFlags flags; + uint32_t generation; + uint32_t ownerClientID; + uint32_t ownerGeneration; + // Input ownership lease duration in milliseconds. + uint32_t lease; + uint32_t maxButtons; +} +KVMFRInputStatus; + +#if defined(__cplusplus) +static_assert(sizeof(KVMFRInputMouseRelative) == 16, + "KVMFR relative mouse input layout changed"); +static_assert(sizeof(KVMFRInputMouseAbsolute) == 16, + "KVMFR absolute mouse input layout changed"); +static_assert(sizeof(KVMFRInputKeyboard) == 16, + "KVMFR keyboard input layout changed"); +static_assert(sizeof(KVMFRInputPayload) == 16, + "KVMFR input payload layout changed"); +static_assert(offsetof(KVMFRInputMessage, payload) == 16, + "KVMFR input message header layout changed"); +static_assert(sizeof(KVMFRInputMessage) == 32, + "KVMFR input message layout changed"); +static_assert(sizeof(KVMFRInputStatus) == 32, + "KVMFR input status layout changed"); +static_assert(sizeof(KVMFRInputMessage) <= 64, + "KVMFR input message must fit in one LGMP control message"); +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +_Static_assert(sizeof(KVMFRInputMouseRelative) == 16, + "KVMFR relative mouse input layout changed"); +_Static_assert(sizeof(KVMFRInputMouseAbsolute) == 16, + "KVMFR absolute mouse input layout changed"); +_Static_assert(sizeof(KVMFRInputKeyboard) == 16, + "KVMFR keyboard input layout changed"); +_Static_assert(sizeof(KVMFRInputPayload) == 16, + "KVMFR input payload layout changed"); +_Static_assert(offsetof(KVMFRInputMessage, payload) == 16, + "KVMFR input message header layout changed"); +_Static_assert(sizeof(KVMFRInputMessage) == 32, + "KVMFR input message layout changed"); +_Static_assert(sizeof(KVMFRInputStatus) == 32, + "KVMFR input status layout changed"); +_Static_assert(sizeof(KVMFRInputMessage) <= 64, + "KVMFR input message must fit in one LGMP control message"); +#endif + +#endif diff --git a/common/include/common/LGMPConfig.h b/common/include/common/LGMPConfig.h index 263bc183..698dea92 100644 --- a/common/include/common/LGMPConfig.h +++ b/common/include/common/LGMPConfig.h @@ -25,11 +25,13 @@ #define LGMP_Q_FRAME 2 // Base ID for LGMP_Q_FRAME_LEN independent owner-delivery queues. #define LGMP_Q_FRAME_OWNER 3 +#define LGMP_Q_INPUT 5 // Two delivery lanes plus a spare buffer let the timing owner continue to // alternate buffers while a secondary client holds the shared delivery. #define LGMP_Q_FRAME_LEN 2 #define LGMP_Q_FRAME_BUFFER_LEN 3 #define LGMP_Q_POINTER_LEN 32 +#define LGMP_Q_INPUT_LEN 4 #endif