mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-21 22:51:31 +00:00
Report guest HID keyboard LED state from LGInput to LGIdd and publish it with the LGMP input endpoint status. Forward SPICE modifier updates through the same provider state so evdev can synchronize physical keyboard LEDs across transport changes and reconnects. Bump the versioned pipe and KVMFR input status contracts for the new feedback state. Accept earlier LGMP input status versions without LED feedback so the client retains input while the guest driver is being upgraded.
247 lines
8.1 KiB
C
247 lines
8.1 KiB
C
/**
|
|
* 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 "KVMFRStream.h"
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#define KVMFR_INPUT_VERSION 3
|
|
#define KVMFR_INPUT_KEYBOARD_LEDS_VERSION 3
|
|
#define KVMFR_INPUT_STREAM_VERSION 1
|
|
#define KVMFR_INPUT_STREAM_ENDPOINT_COUNT 8
|
|
#define KVMFR_INPUT_STREAM_SLOT_COUNT 128
|
|
#define KVMFR_INPUT_STREAM_SLOT_SIZE 64
|
|
#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;
|
|
|
|
/*
|
|
* Input messages are carried by the client's ordered stream endpoint. CLAIM
|
|
* is sequence one, reports, KEEPALIVE and RESET increment the sequence, and
|
|
* RELEASE is the final record.
|
|
*/
|
|
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_KEYBOARD_LED_NUM_LOCK = 0x1,
|
|
KVMFR_INPUT_KEYBOARD_LED_CAPS_LOCK = 0x2,
|
|
KVMFR_INPUT_KEYBOARD_LED_SCROLL_LOCK = 0x4,
|
|
KVMFR_INPUT_KEYBOARD_LED_COMPOSE = 0x8,
|
|
KVMFR_INPUT_KEYBOARD_LED_KANA = 0x10,
|
|
};
|
|
|
|
typedef uint8_t KVMFRInputKeyboardLEDFlags;
|
|
|
|
enum
|
|
{
|
|
KVMFR_INPUT_STATUS_AVAILABLE = 0x1,
|
|
KVMFR_INPUT_STATUS_HAS_OWNER = 0x2,
|
|
KVMFR_INPUT_STATUS_KEYBOARD_LEDS_VALID = 0x4,
|
|
};
|
|
|
|
typedef uint32_t KVMFRInputStatusFlags;
|
|
|
|
enum
|
|
{
|
|
KVMFR_INPUT_STREAM_ENDPOINT_AVAILABLE = 0x1,
|
|
KVMFR_INPUT_STREAM_ENDPOINT_BOUND = 0x2,
|
|
};
|
|
|
|
typedef uint32_t KVMFRInputStreamEndpointFlags;
|
|
|
|
/*
|
|
* A bound endpoint is usable only by boundClientID for bindingGeneration. The
|
|
* host changes bindingGeneration before reusing an endpoint so stale writers
|
|
* can never be accepted as a new client.
|
|
*/
|
|
typedef struct KVMFRInputStreamEndpoint
|
|
{
|
|
KVMFRStreamDescriptor stream;
|
|
uint32_t boundClientID;
|
|
uint32_t bindingGeneration;
|
|
KVMFRInputStreamEndpointFlags flags;
|
|
uint32_t reserved;
|
|
}
|
|
KVMFRInputStreamEndpoint;
|
|
|
|
/*
|
|
* Published through the LGMP input queue for status and stream discovery.
|
|
* KVMFRInputMessage records are carried only by the bound stream endpoint.
|
|
*/
|
|
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;
|
|
uint32_t streamVersion;
|
|
uint32_t streamEndpointCount;
|
|
uint32_t streamGeneration;
|
|
// USB HID keyboard LED bits; valid only when the status flag is set.
|
|
uint8_t keyboardLEDs;
|
|
uint8_t statusReserved[3];
|
|
uint32_t streamReserved[4];
|
|
KVMFRInputStreamEndpoint streamEndpoint[
|
|
KVMFR_INPUT_STREAM_ENDPOINT_COUNT];
|
|
}
|
|
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(KVMFRInputStreamEndpoint) == 48,
|
|
"KVMFR input stream endpoint layout changed");
|
|
static_assert(offsetof(KVMFRInputStatus, streamVersion) == 32,
|
|
"KVMFR input status stream layout changed");
|
|
static_assert(offsetof(KVMFRInputStatus, keyboardLEDs) == 44,
|
|
"KVMFR input status keyboard LED layout changed");
|
|
static_assert(offsetof(KVMFRInputStatus, streamEndpoint) == 64,
|
|
"KVMFR input stream discovery layout changed");
|
|
static_assert(sizeof(KVMFRInputStatus) == 448,
|
|
"KVMFR input status layout changed");
|
|
static_assert(sizeof(KVMFRInputMessage) <= KVMFR_INPUT_STREAM_SLOT_SIZE,
|
|
"KVMFR input message must fit in one stream record");
|
|
#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(KVMFRInputStreamEndpoint) == 48,
|
|
"KVMFR input stream endpoint layout changed");
|
|
_Static_assert(offsetof(KVMFRInputStatus, streamVersion) == 32,
|
|
"KVMFR input status stream layout changed");
|
|
_Static_assert(offsetof(KVMFRInputStatus, keyboardLEDs) == 44,
|
|
"KVMFR input status keyboard LED layout changed");
|
|
_Static_assert(offsetof(KVMFRInputStatus, streamEndpoint) == 64,
|
|
"KVMFR input stream discovery layout changed");
|
|
_Static_assert(sizeof(KVMFRInputStatus) == 448,
|
|
"KVMFR input status layout changed");
|
|
_Static_assert(sizeof(KVMFRInputMessage) <= KVMFR_INPUT_STREAM_SLOT_SIZE,
|
|
"KVMFR input message must fit in one stream record");
|
|
#endif
|
|
|
|
#endif
|