mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-common
synced 2025-12-26 05:26:09 +00:00
1399 lines
29 KiB
Protocol Buffer
1399 lines
29 KiB
Protocol Buffer
/* built in types:
|
|
int8, uint8, 16, 32, 64
|
|
*/
|
|
|
|
typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4);
|
|
|
|
/* IDs of the video stream messages.
|
|
* These IDs are in the interval [0, SPICE_MAX_NUM_STREAMS)
|
|
*/
|
|
typedef stream_id_t uint32;
|
|
|
|
struct Point {
|
|
int32 x;
|
|
int32 y;
|
|
};
|
|
|
|
struct Point16 {
|
|
int16 x;
|
|
int16 y;
|
|
};
|
|
|
|
struct PointFix {
|
|
fixed28_4 x;
|
|
fixed28_4 y;
|
|
};
|
|
|
|
struct Rect {
|
|
int32 top;
|
|
int32 left;
|
|
int32 bottom;
|
|
int32 right;
|
|
};
|
|
|
|
struct Transform {
|
|
uint32 t00;
|
|
uint32 t01;
|
|
uint32 t02;
|
|
uint32 t10;
|
|
uint32 t11;
|
|
uint32 t12;
|
|
};
|
|
|
|
enum32 link_err {
|
|
OK,
|
|
ERROR,
|
|
INVALID_MAGIC,
|
|
INVALID_DATA,
|
|
VERSION_MISMATCH,
|
|
NEED_SECURED,
|
|
NEED_UNSECURED,
|
|
PERMISSION_DENIED,
|
|
BAD_CONNECTION_ID,
|
|
CHANNEL_NOT_AVAILABLE
|
|
};
|
|
|
|
enum32 warn_code {
|
|
WARN_GENERAL
|
|
} @prefix(SPICE_);
|
|
|
|
enum32 info_code {
|
|
INFO_GENERAL
|
|
} @prefix(SPICE_);
|
|
|
|
flags32 migrate_flags {
|
|
NEED_FLUSH,
|
|
NEED_DATA_TRANSFER
|
|
} @prefix(SPICE_MIGRATE_);
|
|
|
|
flags32 composite_flags {
|
|
OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7,
|
|
SRC_FILTER0, SRC_FILTER1, SRC_FILTER2,
|
|
MASK_FILTER0, MASK_FITLER1, MASK_FILTER2,
|
|
|
|
SRC_REPEAT0, SRC_REPEAT1,
|
|
MASK_REPEAT0, MASK_REPEAT1,
|
|
COMPONENT_ALPHA,
|
|
|
|
HAS_MASK,
|
|
HAS_SRC_TRANSFORM,
|
|
HAS_MASK_TRANSFORM,
|
|
|
|
/* These are used to override the formats given in the images. For
|
|
* example, if the mask image has format a8r8g8b8, but MASK_OPAQUE
|
|
* is set, the image should be treated as if it were x8r8g8b8
|
|
*/
|
|
SOURCE_OPAQUE,
|
|
MASK_OPAQUE,
|
|
DEST_OPAQUE,
|
|
} @prefix(SPICE_COMPOSITE_);
|
|
|
|
enum32 notify_severity {
|
|
INFO,
|
|
WARN,
|
|
ERROR,
|
|
};
|
|
|
|
enum32 notify_visibility {
|
|
LOW,
|
|
MEDIUM,
|
|
HIGH,
|
|
};
|
|
|
|
flags16 mouse_mode {
|
|
SERVER,
|
|
CLIENT,
|
|
};
|
|
|
|
message Empty {
|
|
} @declare;
|
|
|
|
message Data {
|
|
uint8 data[] @end;
|
|
} @nocopy @declare;
|
|
|
|
enum8 data_compression_type {
|
|
NONE,
|
|
LZ4,
|
|
};
|
|
|
|
struct EmptyStructure {
|
|
};
|
|
|
|
message CompressedData {
|
|
data_compression_type type;
|
|
switch (type) {
|
|
/* we cannot use !NONE (works only with flags) */
|
|
case NONE:
|
|
/* due to the way cases are defined after NONE we must have something */
|
|
/* due to a bug we cannot use @virtual to write 0 to compressed_size */
|
|
EmptyStructure empty;
|
|
default:
|
|
uint32 uncompressed_size;
|
|
} u @anon;
|
|
uint8 compressed_data[] @as_ptr(compressed_size);
|
|
} @ctype(SpiceMsgCompressedData);
|
|
|
|
struct ChannelWait {
|
|
uint8 channel_type;
|
|
uint8 channel_id;
|
|
uint64 message_serial;
|
|
} @ctype(SpiceWaitForChannel) @declare;
|
|
|
|
channel BaseChannel {
|
|
server:
|
|
message {
|
|
migrate_flags flags;
|
|
} @declare migrate;
|
|
|
|
Data migrate_data;
|
|
|
|
message {
|
|
uint32 generation;
|
|
uint32 window;
|
|
} @declare set_ack;
|
|
|
|
message {
|
|
uint32 id;
|
|
uint64 timestamp;
|
|
uint8 data[] @as_ptr(data_len);
|
|
} @declare ping;
|
|
|
|
message {
|
|
uint8 wait_count;
|
|
ChannelWait wait_list[wait_count] @end;
|
|
} @declare wait_for_channels;
|
|
|
|
message {
|
|
uint64 time_stamp;
|
|
link_err reason;
|
|
} @ctype(SpiceMsgDisconnect) @declare disconnecting;
|
|
|
|
message {
|
|
uint64 time_stamp;
|
|
notify_severity severity;
|
|
notify_visibility visibilty;
|
|
uint32 what; /* error_code/warn_code/info_code */
|
|
uint32 message_len;
|
|
uint8 message[message_len] @end @nomarshal;
|
|
} @declare notify;
|
|
|
|
Data list; /* the msg body is SpiceSubMessageList */
|
|
|
|
Empty base_last = 100;
|
|
|
|
client:
|
|
message {
|
|
uint32 generation;
|
|
} @declare ack_sync;
|
|
|
|
Empty ack;
|
|
|
|
message {
|
|
uint32 id;
|
|
uint64 timestamp;
|
|
} @ctype(SpiceMsgPing) pong;
|
|
|
|
Empty migrate_flush_mark;
|
|
|
|
Data migrate_data;
|
|
|
|
message {
|
|
uint64 time_stamp;
|
|
link_err reason;
|
|
} @ctype(SpiceMsgDisconnect) disconnecting;
|
|
};
|
|
|
|
struct ChannelId {
|
|
uint8 type;
|
|
uint8 id;
|
|
} @declare;
|
|
|
|
struct DstInfo {
|
|
uint16 port;
|
|
uint16 sport;
|
|
uint32 host_size;
|
|
uint8 *host_data[host_size] @zero_terminated @marshall @nonnull;
|
|
uint32 cert_subject_size;
|
|
uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall;
|
|
} @ctype(SpiceMigrationDstInfo) @declare;
|
|
|
|
channel MainChannel : BaseChannel {
|
|
server:
|
|
message {
|
|
DstInfo dst_info;
|
|
} @ctype(SpiceMsgMainMigrationBegin) @declare migrate_begin = 101;
|
|
|
|
Empty migrate_cancel;
|
|
|
|
message {
|
|
uint32 session_id;
|
|
uint32 display_channels_hint;
|
|
uint32 supported_mouse_modes;
|
|
uint32 current_mouse_mode;
|
|
uint32 agent_connected;
|
|
uint32 agent_tokens;
|
|
uint32 multi_media_time;
|
|
uint32 ram_hint;
|
|
} @declare init;
|
|
|
|
message {
|
|
uint32 num_of_channels;
|
|
ChannelId channels[num_of_channels] @end;
|
|
} @ctype(SpiceMsgChannels) @declare channels_list;
|
|
|
|
message {
|
|
mouse_mode supported_modes;
|
|
mouse_mode current_mode @unique_flag;
|
|
} @declare mouse_mode;
|
|
|
|
message {
|
|
uint32 time;
|
|
} @ctype(SpiceMsgMainMultiMediaTime) @declare multi_media_time;
|
|
|
|
Empty agent_connected;
|
|
|
|
message {
|
|
link_err error_code;
|
|
} @ctype(SpiceMsgMainAgentDisconnect) @declare agent_disconnected;
|
|
|
|
Data agent_data;
|
|
|
|
message {
|
|
uint32 num_tokens;
|
|
} @ctype(SpiceMsgMainAgentTokens) @declare agent_token;
|
|
|
|
message {
|
|
uint16 port;
|
|
uint16 sport;
|
|
uint32 host_size;
|
|
uint8 *host_data[host_size] @zero_terminated @marshall;
|
|
uint32 cert_subject_size;
|
|
uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall;
|
|
} @ctype(SpiceMsgMainMigrationSwitchHost) @declare migrate_switch_host;
|
|
|
|
Empty migrate_end;
|
|
|
|
message {
|
|
uint32 name_len;
|
|
uint8 name[name_len] @end;
|
|
} @declare name;
|
|
|
|
message {
|
|
uint8 uuid[16];
|
|
} @declare uuid;
|
|
|
|
message {
|
|
uint32 num_tokens;
|
|
} @declare agent_connected_tokens;
|
|
|
|
message {
|
|
DstInfo dst_info;
|
|
uint32 src_mig_version;
|
|
} @declare migrate_begin_seamless;
|
|
|
|
Empty migrate_dst_seamless_ack;
|
|
Empty migrate_dst_seamless_nack;
|
|
|
|
client:
|
|
message {
|
|
uint64 cache_size;
|
|
} @ctype(SpiceMsgcClientInfo) @declare client_info = 101;
|
|
|
|
Empty migrate_connected;
|
|
|
|
Empty migrate_connect_error;
|
|
|
|
Empty attach_channels;
|
|
|
|
message {
|
|
mouse_mode mode;
|
|
} @declare mouse_mode_request;
|
|
|
|
message {
|
|
uint32 num_tokens;
|
|
} @ctype(SpiceMsgMainAgentTokens) @declare agent_start;
|
|
|
|
Data agent_data;
|
|
|
|
message {
|
|
uint32 num_tokens;
|
|
} @ctype(SpiceMsgMainAgentTokens) @declare agent_token;
|
|
|
|
Empty migrate_end;
|
|
|
|
message {
|
|
uint32 src_version;
|
|
} @declare migrate_dst_do_seamless;
|
|
|
|
Empty migrate_connected_seamless;
|
|
|
|
Data quality_indicator;
|
|
};
|
|
|
|
enum8 clip_type {
|
|
NONE,
|
|
RECTS
|
|
};
|
|
|
|
flags8 path_flags { /* TODO: C enum names changes */
|
|
BEGIN = 0,
|
|
END = 1,
|
|
CLOSE = 3,
|
|
BEZIER = 4,
|
|
} @prefix(SPICE_PATH_);
|
|
|
|
enum8 video_codec_type {
|
|
MJPEG = 1,
|
|
VP8,
|
|
H264,
|
|
VP9,
|
|
H265,
|
|
};
|
|
|
|
flags8 stream_flags {
|
|
TOP_DOWN = 0,
|
|
};
|
|
|
|
enum8 brush_type {
|
|
NONE,
|
|
SOLID,
|
|
PATTERN,
|
|
};
|
|
|
|
flags8 mask_flags {
|
|
INVERS,
|
|
};
|
|
|
|
enum8 image_type {
|
|
BITMAP,
|
|
QUIC,
|
|
RESERVED,
|
|
LZ_PLT = 100,
|
|
LZ_RGB,
|
|
GLZ_RGB,
|
|
FROM_CACHE,
|
|
SURFACE,
|
|
JPEG,
|
|
FROM_CACHE_LOSSLESS,
|
|
ZLIB_GLZ_RGB,
|
|
JPEG_ALPHA,
|
|
LZ4,
|
|
};
|
|
|
|
enum8 image_compression {
|
|
INVALID = 0,
|
|
OFF,
|
|
AUTO_GLZ,
|
|
AUTO_LZ,
|
|
QUIC,
|
|
GLZ,
|
|
LZ,
|
|
LZ4,
|
|
};
|
|
|
|
flags8 image_flags {
|
|
CACHE_ME,
|
|
HIGH_BITS_SET,
|
|
CACHE_REPLACE_ME,
|
|
};
|
|
|
|
enum8 bitmap_fmt {
|
|
INVALID,
|
|
1BIT_LE,
|
|
1BIT_BE,
|
|
4BIT_LE,
|
|
4BIT_BE,
|
|
8BIT /* 8bit indexed mode */,
|
|
16BIT, /* 0555 mode */
|
|
24BIT /* 3 byte, brg */,
|
|
32BIT /* 4 byte, xrgb in little endian format */,
|
|
RGBA /* 4 byte, argb in little endian format */,
|
|
8BIT_A /* 1 byte, alpha */
|
|
};
|
|
|
|
flags8 bitmap_flags {
|
|
PAL_CACHE_ME,
|
|
PAL_FROM_CACHE,
|
|
TOP_DOWN,
|
|
};
|
|
|
|
flags8 jpeg_alpha_flags {
|
|
TOP_DOWN,
|
|
};
|
|
|
|
enum8 image_scale_mode {
|
|
INTERPOLATE,
|
|
NEAREST,
|
|
};
|
|
|
|
flags16 ropd {
|
|
INVERS_SRC,
|
|
INVERS_BRUSH,
|
|
INVERS_DEST,
|
|
OP_PUT,
|
|
OP_OR,
|
|
OP_AND,
|
|
OP_XOR,
|
|
OP_BLACKNESS,
|
|
OP_WHITENESS,
|
|
OP_INVERS,
|
|
INVERS_RES,
|
|
};
|
|
|
|
/* This *must* remain with values identical to api/winddi.h
|
|
LA_STYLED == 0x8 (log_2)=> 3
|
|
LA_STARTGAP == 0x4 (log_2)=> 2
|
|
This is used by the windows driver.
|
|
*/
|
|
flags8 line_flags {
|
|
STYLED = 3,
|
|
START_WITH_GAP = 2,
|
|
};
|
|
|
|
flags8 string_flags {
|
|
RASTER_A1,
|
|
RASTER_A4,
|
|
RASTER_A8,
|
|
RASTER_TOP_DOWN,
|
|
};
|
|
|
|
flags32 surface_flags {
|
|
/* Adding flags requires some caps check, since old clients only
|
|
treat the value as an enum and not as a flag (flag == PRIMARY).
|
|
Considering this was fixed by commit
|
|
5b6e3d1c16457c926322ce28d341af2e8d39efb5 in Aug 21 2013 is safe
|
|
to assume that if capabilities include SPICE_DISPLAY_CAP_MULTI_CODEC
|
|
we can use any flags */
|
|
PRIMARY,
|
|
/* The surface will be streamed entirely. This means that only
|
|
stream commands will be received and the stream will cover the
|
|
entire surface. This flag can be safely ignored and is intended
|
|
as an hint for the client */
|
|
STREAMING_MODE,
|
|
};
|
|
|
|
enum32 surface_fmt {
|
|
INVALID,
|
|
1_A = 1,
|
|
8_A = 8,
|
|
16_555 = 16 ,
|
|
16_565 = 80,
|
|
32_xRGB = 32,
|
|
32_ARGB = 96
|
|
};
|
|
|
|
flags8 alpha_flags {
|
|
DEST_HAS_ALPHA,
|
|
SRC_SURFACE_HAS_ALPHA
|
|
};
|
|
|
|
enum8 resource_type {
|
|
INVALID,
|
|
PIXMAP
|
|
} @prefix(SPICE_RES_TYPE_);
|
|
|
|
struct ClipRects {
|
|
uint32 num_rects;
|
|
Rect rects[num_rects] @end;
|
|
};
|
|
|
|
struct PathSegment {
|
|
path_flags flags;
|
|
uint32 count;
|
|
PointFix points[count] @end;
|
|
} @ctype(SpicePathSeg);
|
|
|
|
struct Path {
|
|
uint32 num_segments;
|
|
PathSegment segments[num_segments] @ptr_array;
|
|
};
|
|
|
|
struct Clip {
|
|
clip_type type;
|
|
switch (type) {
|
|
case RECTS:
|
|
ClipRects rects @outvar(cliprects) @to_ptr;
|
|
} u @anon;
|
|
};
|
|
|
|
struct DisplayBase {
|
|
uint32 surface_id;
|
|
Rect box;
|
|
Clip clip;
|
|
} @ctype(SpiceMsgDisplayBase) @declare;
|
|
|
|
struct ResourceID {
|
|
uint8 type; /* resource_type */
|
|
uint64 id;
|
|
} @declare;
|
|
|
|
struct WaitForChannel {
|
|
uint8 channel_type;
|
|
uint8 channel_id;
|
|
uint64 message_serial;
|
|
} @declare;
|
|
|
|
struct Palette {
|
|
uint64 unique;
|
|
uint16 num_ents;
|
|
uint32 ents[num_ents] @end;
|
|
};
|
|
|
|
struct BitmapData {
|
|
bitmap_fmt format;
|
|
bitmap_flags flags;
|
|
uint32 x;
|
|
uint32 y;
|
|
uint32 stride;
|
|
switch (flags) {
|
|
case PAL_FROM_CACHE:
|
|
uint64 palette_id;
|
|
default:
|
|
Palette *palette @outvar(bitmap);
|
|
} pal @anon;
|
|
uint8 data[image_size(8, stride, y)] @chunk @nomarshal;
|
|
} @ctype(SpiceBitmap);
|
|
|
|
struct BinaryData {
|
|
uint32 data_size;
|
|
uint8 data[data_size] @nomarshal @chunk;
|
|
} @ctype(SpiceQUICData);
|
|
|
|
struct LZPLTData {
|
|
bitmap_flags flags;
|
|
uint32 data_size;
|
|
switch (flags) {
|
|
case PAL_FROM_CACHE:
|
|
uint64 palette_id;
|
|
default:
|
|
Palette *palette @nonnull @outvar(lzplt);
|
|
} pal @anon;
|
|
uint8 data[data_size] @nomarshal @chunk;
|
|
};
|
|
|
|
struct ZlibGlzRGBData {
|
|
uint32 glz_data_size;
|
|
uint32 data_size;
|
|
uint8 data[data_size] @nomarshal @chunk;
|
|
} @ctype(SpiceZlibGlzRGBData);
|
|
|
|
struct JPEGAlphaData {
|
|
jpeg_alpha_flags flags;
|
|
uint32 jpeg_size;
|
|
uint32 data_size;
|
|
uint8 data[data_size] @nomarshal @chunk;
|
|
} @ctype(SpiceJPEGAlphaData);
|
|
|
|
struct Surface {
|
|
uint32 surface_id;
|
|
};
|
|
|
|
|
|
struct Image {
|
|
struct ImageDescriptor {
|
|
uint64 id;
|
|
image_type type;
|
|
image_flags flags;
|
|
uint32 width;
|
|
uint32 height;
|
|
} descriptor;
|
|
|
|
switch (descriptor.type) {
|
|
case BITMAP:
|
|
BitmapData bitmap;
|
|
case QUIC:
|
|
BinaryData quic;
|
|
case LZ_RGB:
|
|
case GLZ_RGB:
|
|
BinaryData lz_rgb;
|
|
case JPEG:
|
|
BinaryData jpeg;
|
|
case LZ4:
|
|
BinaryData lz4;
|
|
case LZ_PLT:
|
|
LZPLTData lz_plt;
|
|
case ZLIB_GLZ_RGB:
|
|
ZlibGlzRGBData zlib_glz;
|
|
case JPEG_ALPHA:
|
|
JPEGAlphaData jpeg_alpha;
|
|
case SURFACE:
|
|
Surface surface;
|
|
} u;
|
|
};
|
|
|
|
struct Pattern {
|
|
Image *pat @nonnull;
|
|
Point pos;
|
|
};
|
|
|
|
struct Brush {
|
|
brush_type type;
|
|
switch (type) {
|
|
case SOLID:
|
|
uint32 color;
|
|
case PATTERN:
|
|
Pattern pattern;
|
|
} u;
|
|
};
|
|
|
|
struct QMask {
|
|
mask_flags flags;
|
|
Point pos;
|
|
Image *bitmap;
|
|
};
|
|
|
|
struct LineAttr {
|
|
line_flags flags;
|
|
switch (flags) {
|
|
case STYLED:
|
|
uint8 style_nseg;
|
|
} u1 @anon;
|
|
switch (flags) {
|
|
case STYLED:
|
|
fixed28_4 *style[style_nseg];
|
|
} u2 @anon;
|
|
};
|
|
|
|
struct RasterGlyphA1 {
|
|
Point render_pos;
|
|
Point glyph_origin;
|
|
uint16 width;
|
|
uint16 height;
|
|
uint8 data[image_size(1, width, height)] @end;
|
|
} @ctype(SpiceRasterGlyph);
|
|
|
|
struct RasterGlyphA4 {
|
|
Point render_pos;
|
|
Point glyph_origin;
|
|
uint16 width;
|
|
uint16 height;
|
|
uint8 data[image_size(4, width, height)] @end;
|
|
} @ctype(SpiceRasterGlyph);
|
|
|
|
struct RasterGlyphA8 {
|
|
Point render_pos;
|
|
Point glyph_origin;
|
|
uint16 width;
|
|
uint16 height;
|
|
uint8 data[image_size(8, width, height)] @end;
|
|
} @ctype(SpiceRasterGlyph);
|
|
|
|
struct String {
|
|
uint16 length;
|
|
string_flags flags; /* Special: Only one of a1/a4/a8 set */
|
|
switch (flags) {
|
|
case RASTER_A1:
|
|
RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
|
|
case RASTER_A4:
|
|
RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
|
|
case RASTER_A8:
|
|
RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array;
|
|
} u @anon;
|
|
};
|
|
|
|
struct StreamDataHeader {
|
|
stream_id_t id;
|
|
uint32 multi_media_time;
|
|
} @declare;
|
|
|
|
struct Head {
|
|
uint32 monitor_id;
|
|
uint32 surface_id;
|
|
uint32 width;
|
|
uint32 height;
|
|
uint32 x;
|
|
uint32 y;
|
|
uint32 flags;
|
|
} @declare;
|
|
|
|
flags32 gl_scanout_flags {
|
|
Y0TOP
|
|
};
|
|
|
|
struct GlPlaneUnix {
|
|
unix_fd fd;
|
|
uint32 offset;
|
|
uint32 stride;
|
|
} @declare;
|
|
|
|
channel DisplayChannel : BaseChannel {
|
|
server:
|
|
message {
|
|
uint32 x_res;
|
|
uint32 y_res;
|
|
uint32 bits;
|
|
} @declare mode = 101;
|
|
|
|
Empty mark;
|
|
Empty reset;
|
|
message {
|
|
DisplayBase base;
|
|
Point src_pos;
|
|
} @declare copy_bits;
|
|
|
|
message {
|
|
uint16 count;
|
|
ResourceID resources[count] @end;
|
|
} @ctype(SpiceResourceList) @declare inval_list;
|
|
|
|
/* This message is used to invalidate the complete image cache
|
|
* on the client.
|
|
* Due to synchronization for GLZ images we must make sure
|
|
* that messages related to cached images on other channels
|
|
* are processed so we send a list of channels with respective
|
|
* message serials to wait for.
|
|
*/
|
|
message {
|
|
uint8 wait_count;
|
|
WaitForChannel wait_list[wait_count] @end;
|
|
} @ctype(SpiceMsgWaitForChannels) @declare inval_all_pixmaps;
|
|
|
|
message {
|
|
uint64 id;
|
|
} @ctype(SpiceMsgDisplayInvalOne) @declare inval_palette;
|
|
|
|
Empty inval_all_palettes;
|
|
|
|
message {
|
|
uint32 surface_id;
|
|
stream_id_t id;
|
|
stream_flags flags;
|
|
video_codec_type codec_type;
|
|
uint64 stamp;
|
|
uint32 stream_width;
|
|
uint32 stream_height;
|
|
uint32 src_width;
|
|
uint32 src_height;
|
|
Rect dest;
|
|
Clip clip;
|
|
} @declare stream_create = 122;
|
|
|
|
message {
|
|
StreamDataHeader base;
|
|
uint32 data_size;
|
|
uint8 data[data_size] @end @nomarshal;
|
|
} @declare stream_data;
|
|
|
|
message {
|
|
stream_id_t id;
|
|
Clip clip;
|
|
} @declare stream_clip;
|
|
|
|
message {
|
|
stream_id_t id;
|
|
} @declare stream_destroy;
|
|
|
|
Empty stream_destroy_all;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Fill {
|
|
Brush brush @outvar(brush);
|
|
ropd rop_descriptor;
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_fill = 302;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Opaque {
|
|
Image *src_bitmap;
|
|
Rect src_area;
|
|
Brush brush;
|
|
ropd rop_descriptor;
|
|
image_scale_mode scale_mode;
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_opaque;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Copy {
|
|
Image *src_bitmap;
|
|
Rect src_area;
|
|
ropd rop_descriptor;
|
|
image_scale_mode scale_mode;
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_copy;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Blend {
|
|
Image *src_bitmap;
|
|
Rect src_area;
|
|
ropd rop_descriptor;
|
|
image_scale_mode scale_mode;
|
|
QMask mask @outvar(mask);
|
|
} @ctype(SpiceCopy) data;
|
|
} @ctype(SpiceMsgDisplayDrawCopy) draw_blend;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Blackness {
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_blackness;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Whiteness {
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_whiteness;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Invers {
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_invers;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Rop3 {
|
|
Image *src_bitmap;
|
|
Rect src_area;
|
|
Brush brush;
|
|
uint8 rop3;
|
|
image_scale_mode scale_mode;
|
|
QMask mask @outvar(mask);
|
|
} data;
|
|
} @declare draw_rop3;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Stroke {
|
|
Path *path @marshall @nonnull;
|
|
LineAttr attr;
|
|
Brush brush;
|
|
uint16 fore_mode;
|
|
uint16 back_mode;
|
|
} data;
|
|
} @declare draw_stroke;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Text {
|
|
String *str @marshall @nonnull;
|
|
Rect back_area;
|
|
Brush fore_brush @outvar(fore_brush);
|
|
Brush back_brush @outvar(back_brush);
|
|
uint16 fore_mode;
|
|
uint16 back_mode;
|
|
} data;
|
|
} @declare draw_text;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Transparent {
|
|
Image *src_bitmap;
|
|
Rect src_area;
|
|
uint32 src_color;
|
|
uint32 true_color;
|
|
} data;
|
|
} @declare draw_transparent;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct AlphaBlend {
|
|
alpha_flags alpha_flags;
|
|
uint8 alpha;
|
|
Image *src_bitmap;
|
|
Rect src_area;
|
|
} data;
|
|
} @declare draw_alpha_blend;
|
|
|
|
message {
|
|
uint32 surface_id;
|
|
uint32 width;
|
|
uint32 height;
|
|
surface_fmt format;
|
|
surface_flags flags;
|
|
} @ctype(SpiceMsgSurfaceCreate) @declare surface_create;
|
|
|
|
message {
|
|
uint32 surface_id;
|
|
} @ctype(SpiceMsgSurfaceDestroy) @declare surface_destroy;
|
|
|
|
message {
|
|
StreamDataHeader base;
|
|
uint32 width;
|
|
uint32 height;
|
|
Rect dest;
|
|
uint32 data_size;
|
|
uint8 data[data_size] @end @nomarshal;
|
|
} @declare stream_data_sized;
|
|
|
|
message {
|
|
uint16 count;
|
|
uint16 max_allowed;
|
|
Head heads[count] @end;
|
|
} @declare monitors_config;
|
|
|
|
message {
|
|
DisplayBase base;
|
|
struct Composite {
|
|
composite_flags flags;
|
|
Image *src_bitmap;
|
|
switch (flags) {
|
|
case HAS_MASK:
|
|
Image *mask_bitmap;
|
|
} a @anon;
|
|
switch (flags) {
|
|
case HAS_SRC_TRANSFORM:
|
|
Transform src_transform;
|
|
} b @anon;
|
|
switch (flags) {
|
|
case HAS_MASK_TRANSFORM:
|
|
Transform mask_transform;
|
|
} c @anon;
|
|
Point16 src_origin;
|
|
Point16 mask_origin;
|
|
} data;
|
|
} @declare draw_composite;
|
|
|
|
message {
|
|
stream_id_t stream_id;
|
|
uint32 unique_id;
|
|
uint32 max_window_size;
|
|
uint32 timeout_ms;
|
|
} @declare stream_activate_report;
|
|
|
|
message {
|
|
unix_fd drm_dma_buf_fd;
|
|
uint32 width;
|
|
uint32 height;
|
|
uint32 stride;
|
|
/* specifies the format of drm_dma_buf_fd defined in drm_fourcc.h */
|
|
uint32 drm_fourcc_format;
|
|
gl_scanout_flags flags;
|
|
} @declare gl_scanout_unix;
|
|
|
|
message {
|
|
uint32 x;
|
|
uint32 y;
|
|
uint32 w;
|
|
uint32 h;
|
|
} @declare gl_draw;
|
|
|
|
Data quality_indicator;
|
|
|
|
message {
|
|
uint32 width;
|
|
uint32 height;
|
|
/* pixel format, see drm_fourcc.h */
|
|
uint32 fourcc;
|
|
gl_scanout_flags flags;
|
|
/* max 4 planes */
|
|
uint8 num_planes;
|
|
/* pixel layout in the buffer, see drm_fourcc.h */
|
|
uint64 modifier;
|
|
GlPlaneUnix planes[num_planes] @end;
|
|
} @declare gl_scanout2_unix;
|
|
|
|
client:
|
|
message {
|
|
uint8 pixmap_cache_id;
|
|
int64 pixmap_cache_size; //in pixels
|
|
uint8 glz_dictionary_id;
|
|
int32 glz_dictionary_window_size; // in pixels
|
|
} @declare init = 101;
|
|
|
|
message {
|
|
stream_id_t stream_id;
|
|
uint32 unique_id;
|
|
// the mm_time of the first frame included in the report
|
|
uint32 start_frame_mm_time;
|
|
// the mm_time of the last frame included in the report
|
|
uint32 end_frame_mm_time;
|
|
// the number of frames that reached the client during the time the
|
|
// report is referring to
|
|
// A special case is when num_frames == 0 and num_drops ==
|
|
// 0xffffffffu, this is used in the client to communicate that
|
|
// the stream is not supported or that the client was not able
|
|
// to decode it
|
|
uint32 num_frames;
|
|
// the part of the above frames that were dropped by the client due
|
|
// to late arrival time
|
|
uint32 num_drops;
|
|
// end_frame_mm_time - client_mm_time
|
|
int32 last_frame_delay;
|
|
// the latency of the audio playback
|
|
// If there is no audio playback, set it to 0xffffffffu
|
|
uint32 audio_delay;
|
|
} @declare stream_report;
|
|
|
|
message {
|
|
image_compression image_compression;
|
|
} @declare preferred_compression;
|
|
|
|
message {
|
|
} @declare gl_draw_done;
|
|
|
|
message {
|
|
uint8 num_of_codecs;
|
|
video_codec_type codecs[num_of_codecs] @end;
|
|
} @declare preferred_video_codec_type;
|
|
};
|
|
|
|
flags16 keyboard_modifier_flags {
|
|
SCROLL_LOCK,
|
|
NUM_LOCK,
|
|
CAPS_LOCK
|
|
};
|
|
|
|
enum8 mouse_button {
|
|
INVALID,
|
|
LEFT,
|
|
MIDDLE,
|
|
RIGHT,
|
|
UP,
|
|
DOWN,
|
|
SIDE,
|
|
EXTRA,
|
|
};
|
|
|
|
flags16 mouse_button_mask {
|
|
LEFT,
|
|
MIDDLE,
|
|
RIGHT,
|
|
UP,
|
|
DOWN,
|
|
SIDE,
|
|
EXTRA,
|
|
};
|
|
|
|
channel InputsChannel : BaseChannel {
|
|
client:
|
|
message {
|
|
uint32 code;
|
|
} @ctype(SpiceMsgcKeyDown) @declare key_down = 101;
|
|
|
|
message {
|
|
uint32 code;
|
|
} @ctype(SpiceMsgcKeyUp) @declare key_up;
|
|
|
|
message {
|
|
keyboard_modifier_flags modifiers;
|
|
} @ctype(SpiceMsgcKeyModifiers) @declare key_modifiers;
|
|
|
|
Data key_scancode;
|
|
|
|
message {
|
|
int32 dx;
|
|
int32 dy;
|
|
mouse_button_mask buttons_state;
|
|
} @ctype(SpiceMsgcMouseMotion) @declare mouse_motion = 111;
|
|
|
|
message {
|
|
uint32 x;
|
|
uint32 y;
|
|
mouse_button_mask buttons_state;
|
|
uint8 display_id;
|
|
} @ctype(SpiceMsgcMousePosition) @declare mouse_position;
|
|
|
|
message {
|
|
mouse_button button;
|
|
mouse_button_mask buttons_state;
|
|
} @ctype(SpiceMsgcMousePress) @declare mouse_press;
|
|
|
|
message {
|
|
mouse_button button;
|
|
mouse_button_mask buttons_state;
|
|
} @ctype(SpiceMsgcMouseRelease) @declare mouse_release;
|
|
|
|
server:
|
|
message {
|
|
keyboard_modifier_flags keyboard_modifiers;
|
|
} @declare init = 101;
|
|
|
|
message {
|
|
keyboard_modifier_flags modifiers;
|
|
} @declare key_modifiers;
|
|
|
|
Empty mouse_motion_ack = 111;
|
|
};
|
|
|
|
enum8 cursor_type {
|
|
ALPHA,
|
|
MONO,
|
|
COLOR4,
|
|
COLOR8,
|
|
COLOR16,
|
|
COLOR24,
|
|
COLOR32,
|
|
};
|
|
|
|
flags16 cursor_flags {
|
|
NONE, /* Means no cursor */
|
|
CACHE_ME,
|
|
FROM_CACHE,
|
|
};
|
|
|
|
struct CursorHeader {
|
|
uint64 unique;
|
|
cursor_type type;
|
|
uint16 width;
|
|
uint16 height;
|
|
uint16 hot_spot_x;
|
|
uint16 hot_spot_y;
|
|
};
|
|
|
|
struct Cursor {
|
|
cursor_flags flags;
|
|
switch (flags) {
|
|
case !NONE:
|
|
CursorHeader header;
|
|
} u @anon;
|
|
uint8 data[] @as_ptr(data_size);
|
|
} @declare;
|
|
|
|
channel CursorChannel : BaseChannel {
|
|
server:
|
|
message {
|
|
Point16 position;
|
|
uint16 trail_length;
|
|
uint16 trail_frequency;
|
|
uint8 visible;
|
|
Cursor cursor;
|
|
} @declare init = 101;
|
|
|
|
Empty reset;
|
|
|
|
message {
|
|
Point16 position;
|
|
uint8 visible;
|
|
Cursor cursor;
|
|
} @declare set;
|
|
|
|
message {
|
|
Point16 position;
|
|
} @declare move;
|
|
|
|
Empty hide;
|
|
|
|
message {
|
|
uint16 length;
|
|
uint16 frequency;
|
|
} @declare trail;
|
|
|
|
message {
|
|
uint64 id;
|
|
} @ctype(SpiceMsgDisplayInvalOne) @declare inval_one;
|
|
|
|
Empty inval_all;
|
|
};
|
|
|
|
enum16 audio_data_mode {
|
|
INVALID,
|
|
RAW,
|
|
CELT_0_5_1 @deprecated,
|
|
OPUS,
|
|
};
|
|
|
|
enum16 audio_fmt {
|
|
INVALID,
|
|
S16,
|
|
};
|
|
|
|
message AudioVolume {
|
|
uint8 nchannels;
|
|
uint16 volume[nchannels] @end;
|
|
} @declare;
|
|
|
|
message AudioMute {
|
|
uint8 mute;
|
|
} @declare;
|
|
|
|
channel PlaybackChannel : BaseChannel {
|
|
server:
|
|
message {
|
|
uint32 time;
|
|
uint8 data[] @as_ptr(data_size);
|
|
} @ctype(SpiceMsgPlaybackPacket) @declare data = 101;
|
|
|
|
message {
|
|
uint32 time;
|
|
audio_data_mode mode;
|
|
uint8 data[] @as_ptr(data_size);
|
|
} @declare mode;
|
|
|
|
message {
|
|
uint32 channels;
|
|
audio_fmt format;
|
|
uint32 frequency;
|
|
uint32 time;
|
|
} @declare start;
|
|
|
|
Empty stop;
|
|
AudioVolume volume;
|
|
AudioMute mute;
|
|
|
|
message {
|
|
uint32 latency_ms;
|
|
} @declare latency;
|
|
};
|
|
|
|
channel RecordChannel : BaseChannel {
|
|
server:
|
|
message {
|
|
uint32 channels;
|
|
audio_fmt format;
|
|
uint32 frequency;
|
|
} @declare start = 101;
|
|
|
|
Empty stop;
|
|
AudioVolume volume;
|
|
AudioMute mute;
|
|
client:
|
|
message {
|
|
uint32 time;
|
|
uint8 data[] @nomarshal @as_ptr(data_size);
|
|
} @ctype(SpiceMsgPlaybackPacket) @declare data = 101;
|
|
|
|
message {
|
|
uint32 time;
|
|
audio_data_mode mode;
|
|
uint8 data[] @as_ptr(data_size);
|
|
} @ctype(SpiceMsgPlaybackMode) @declare mode;
|
|
|
|
message {
|
|
uint32 time;
|
|
} @declare start_mark;
|
|
};
|
|
|
|
channel TunnelChannel {
|
|
};
|
|
|
|
enum32 vsc_message_type {
|
|
Init = 1,
|
|
Error,
|
|
ReaderAdd,
|
|
ReaderRemove,
|
|
ATR,
|
|
CardRemove,
|
|
APDU,
|
|
Flush,
|
|
FlushComplete
|
|
};
|
|
|
|
struct VscMessageHeader {
|
|
vsc_message_type type;
|
|
uint32 reader_id;
|
|
uint32 length;
|
|
} @ctype(VSCMsgHeader);
|
|
|
|
struct VscMessageError {
|
|
uint32 code;
|
|
} @ctype(VSCMsgError);
|
|
|
|
struct VscMessageAPDU {
|
|
uint8 data[];
|
|
} @ctype(VSCMsgAPDU);
|
|
|
|
struct VscMessageATR {
|
|
uint8 atr[];
|
|
} @ctype(VSCMsgATR);
|
|
|
|
struct VscMessageReaderAdd {
|
|
int8 *name[] @zero_terminated @nonnull @end @nomarshal;
|
|
} @ctype(VSCMsgReaderAdd);
|
|
|
|
channel SmartcardChannel : BaseChannel {
|
|
server:
|
|
message {
|
|
vsc_message_type type;
|
|
uint32 reader_id;
|
|
uint32 length;
|
|
uint8 data[length] @end @nomarshal;
|
|
} @ctype(SpiceMsgSmartcard) data = 101;
|
|
|
|
client:
|
|
/* Some of the following messages are duplicated, the protocol
|
|
* definition was broken. Messages, as you can see have same ID.
|
|
* Also code was not used and didn't compile correctly.
|
|
* Keeping in the hope could be useful in the future.
|
|
*/
|
|
/*
|
|
message {
|
|
VscMessageHeader header;
|
|
switch (header.type) {
|
|
case ReaderAdd:
|
|
VscMessageReaderAdd add;
|
|
case ATR:
|
|
case APDU:
|
|
VscMessageATR atr_data;
|
|
case Error:
|
|
VscMessageError error;
|
|
} u @anon;
|
|
} @ctype(SpiceMsgcSmartcard) old_data = 101;
|
|
*/
|
|
message {
|
|
vsc_message_type type;
|
|
uint32 reader_id;
|
|
uint32 length;
|
|
uint8 data[length] @end @nomarshal;
|
|
} @ctype(VSCMsgHeader) data = 101;
|
|
/* See comment on client data message above */
|
|
/*
|
|
message {
|
|
uint32 code;
|
|
} @ctype(VSCMsgError) error = 101;
|
|
|
|
message {
|
|
uint8 data[];
|
|
} @ctype(VSCMsgATR) atr = 101;
|
|
|
|
message {
|
|
int8 name[] @zero_terminated @nonnull;
|
|
} @ctype(VSCMsgReaderAdd) reader_add = 101;
|
|
*/
|
|
} @ifdef(USE_SMARTCARD);
|
|
|
|
channel SpicevmcChannel : BaseChannel {
|
|
server:
|
|
Data data = 101;
|
|
CompressedData compressed_data = 102;
|
|
client:
|
|
Data data = 101;
|
|
CompressedData compressed_data = 102;
|
|
};
|
|
|
|
channel UsbredirChannel : SpicevmcChannel {
|
|
};
|
|
|
|
channel PortChannel : SpicevmcChannel {
|
|
client:
|
|
message {
|
|
uint8 event;
|
|
} @declare event = 201;
|
|
server:
|
|
message {
|
|
uint32 name_size;
|
|
uint8 *name[name_size] @zero_terminated @marshall @nonnull;
|
|
uint8 opened;
|
|
} @declare init = 201;
|
|
message {
|
|
uint8 event;
|
|
} @declare event;
|
|
};
|
|
|
|
channel WebDAVChannel : PortChannel {
|
|
};
|
|
|
|
protocol Spice {
|
|
MainChannel main = 1;
|
|
DisplayChannel display;
|
|
InputsChannel inputs;
|
|
CursorChannel cursor;
|
|
PlaybackChannel playback;
|
|
RecordChannel record;
|
|
TunnelChannel tunnel;
|
|
SmartcardChannel smartcard;
|
|
UsbredirChannel usbredir;
|
|
PortChannel port;
|
|
WebDAVChannel webdav;
|
|
};
|