/* built in types: int8, uint8, 16, 32, 64 */ typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4); 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, }; enum16 pubkey_type { INVALID, RSA, RSA2, DSA, DSA1, DSA2, DSA3, DSA4, DH, EC, }; message Empty { }; message Data { uint8 data[] @end @ctype(uint8_t); } @nocopy; struct ChannelWait { uint8 channel_type; uint8 channel_id; uint64 message_serial; } @ctype(SpiceWaitForChannel); channel BaseChannel { server: message { migrate_flags flags; } migrate; Data migrate_data; message { uint32 generation; uint32 window; } set_ack; message { uint32 id; uint64 timestamp; uint8 data[] @ctype(uint8_t) @as_ptr(data_len); } ping; message { uint8 wait_count; ChannelWait wait_list[wait_count] @end; } wait_for_channels; message { uint64 time_stamp; link_err reason; } @ctype(SpiceMsgDisconnect) 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; } notify; Data list; /* the msg body is SpiceSubMessageList */ Empty base_last = 100; client: message { uint32 generation; } 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; }; 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); channel MainChannel : BaseChannel { server: message { DstInfo dst_info; } @ctype(SpiceMsgMainMigrationBegin) 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; } init; message { uint32 num_of_channels; ChannelId channels[num_of_channels] @end; } @ctype(SpiceMsgChannels) channels_list; message { mouse_mode supported_modes; mouse_mode current_mode @unique_flag; } mouse_mode; message { uint32 time; } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time; Empty agent_connected; message { link_err error_code; } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected; Data agent_data; message { uint32 num_tokens; } @ctype(SpiceMsgMainAgentTokens) 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) migrate_switch_host; Empty migrate_end; message { uint32 name_len; uint8 name[name_len] @end; } name; message { uint8 uuid[16]; } uuid; message { uint32 num_tokens; } agent_connected_tokens; message { DstInfo dst_info; uint32 src_mig_version; } migrate_begin_seamless; Empty migrate_dst_seamless_ack; Empty migrate_dst_seamless_nack; client: message { uint64 cache_size; } @ctype(SpiceMsgcClientInfo) client_info = 101; Empty migrate_connected; Empty migrate_connect_error; Empty attach_channels; message { mouse_mode mode; } mouse_mode_request; message { uint32 num_tokens; } agent_start; Data agent_data; message { uint32 num_tokens; } @ctype(SpiceMsgcMainAgentTokens) agent_token; Empty migrate_end; message { uint32 src_version; } migrate_dst_do_seamless; Empty migrate_connected_seamless; }; 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, }; 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) */ PRIMARY }; 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); struct ResourceID { uint8 type; uint64 id; }; struct WaitForChannel { uint8 channel_type; uint8 channel_id; uint64 message_serial; }; 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 { uint32 id; uint32 multi_media_time; }; struct Head { uint32 id; uint32 surface_id; uint32 width; uint32 height; uint32 x; uint32 y; uint32 flags; }; flags32 gl_scanout_flags { Y0TOP }; channel DisplayChannel : BaseChannel { server: message { uint32 x_res; uint32 y_res; uint32 bits; } mode = 101; Empty mark; Empty reset; message { DisplayBase base; Point src_pos; } copy_bits; message { uint16 count; ResourceID resources[count] @end; } @ctype(SpiceResourceList) inval_list; message { uint8 wait_count; WaitForChannel wait_list[wait_count] @end; } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps; message { uint64 id; } @ctype(SpiceMsgDisplayInvalOne) inval_palette; Empty inval_all_palettes; message { uint32 surface_id; uint32 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; } stream_create = 122; message { StreamDataHeader base; uint32 data_size; uint8 data[data_size] @end @nomarshal; } stream_data; message { uint32 id; Clip clip; } stream_clip; message { uint32 id; } stream_destroy; Empty stream_destroy_all; message { DisplayBase base; struct Fill { Brush brush @outvar(brush); ropd rop_descriptor; QMask mask @outvar(mask); } data; } 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; } 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; } 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; } draw_blend; message { DisplayBase base; struct Blackness { QMask mask @outvar(mask); } data; } draw_blackness; message { DisplayBase base; struct Whiteness { QMask mask @outvar(mask); } data; } draw_whiteness; message { DisplayBase base; struct Invers { QMask mask @outvar(mask); } data; } 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; } draw_rop3; message { DisplayBase base; struct Stroke { Path *path @marshall @nonnull; LineAttr attr; Brush brush; uint16 fore_mode; uint16 back_mode; } data; } 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; } draw_text; message { DisplayBase base; struct Transparent { Image *src_bitmap; Rect src_area; uint32 src_color; uint32 true_color; } data; } draw_transparent; message { DisplayBase base; struct AlphaBlend { alpha_flags alpha_flags; uint8 alpha; Image *src_bitmap; Rect src_area; } data; } draw_alpha_blend; message { uint32 surface_id; uint32 width; uint32 height; surface_fmt format; surface_flags flags; } @ctype(SpiceMsgSurfaceCreate) surface_create; message { uint32 surface_id; } @ctype(SpiceMsgSurfaceDestroy) surface_destroy; message { StreamDataHeader base; uint32 width; uint32 height; Rect dest; uint32 data_size; uint8 data[data_size] @end @nomarshal; } stream_data_sized; message { uint16 count; uint16 max_allowed; Head heads[count] @end; } 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; } draw_composite; message { uint32 stream_id; uint32 unique_id; uint32 max_window_size; uint32 timeout_ms; } 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; } gl_scanout_unix; message { uint32 x; uint32 y; uint32 w; uint32 h; } gl_draw; client: message { uint8 pixmap_cache_id; int64 pixmap_cache_size; //in pixels uint8 glz_dictionary_id; int32 glz_dictionary_window_size; // in pixels } init = 101; message { uint32 stream_id; uint32 unique_id; uint32 start_frame_mm_time; uint32 end_frame_mm_time; uint32 num_frames; uint32 num_drops; int32 last_frame_delay; uint32 audio_delay; } stream_report; message { image_compression image_compression; } preferred_compression; message { } gl_draw_done; }; flags16 keyboard_modifier_flags { SCROLL_LOCK, NUM_LOCK, CAPS_LOCK }; enum8 mouse_button { INVALID, LEFT, MIDDLE, RIGHT, UP, DOWN, }; flags16 mouse_button_mask { LEFT, MIDDLE, RIGHT }; channel InputsChannel : BaseChannel { client: message { uint32 code; } @ctype(SpiceMsgcKeyDown) key_down = 101; message { uint32 code; } @ctype(SpiceMsgcKeyUp) key_up; message { keyboard_modifier_flags modifiers; } @ctype(SpiceMsgcKeyModifiers) key_modifiers; Data key_scancode; message { int32 dx; int32 dy; mouse_button_mask buttons_state; } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111; message { uint32 x; uint32 y; mouse_button_mask buttons_state; uint8 display_id; } @ctype(SpiceMsgcMousePosition) mouse_position; message { mouse_button button; mouse_button_mask buttons_state; } @ctype(SpiceMsgcMousePress) mouse_press; message { mouse_button button; mouse_button_mask buttons_state; } @ctype(SpiceMsgcMouseRelease) mouse_release; server: message { keyboard_modifier_flags keyboard_modifiers; } init = 101; message { keyboard_modifier_flags modifiers; } 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); }; channel CursorChannel : BaseChannel { server: message { Point16 position; uint16 trail_length; uint16 trail_frequency; uint8 visible; Cursor cursor; } init = 101; Empty reset; message { Point16 position; uint8 visible; Cursor cursor; } set; message { Point16 position; } move; Empty hide; message { uint16 length; uint16 frequency; } trail; message { uint64 id; } @ctype(SpiceMsgDisplayInvalOne) inval_one; Empty inval_all; }; enum16 audio_data_mode { INVALID, RAW, CELT_0_5_1, OPUS, }; enum16 audio_fmt { INVALID, S16, }; message AudioVolume { uint8 nchannels; uint16 volume[nchannels] @end; }; message AudioMute { uint8 mute; }; channel PlaybackChannel : BaseChannel { server: message { uint32 time; uint8 data[] @as_ptr(data_size); } @ctype(SpiceMsgPlaybackPacket) data = 101; message { uint32 time; audio_data_mode mode; uint8 data[] @as_ptr(data_size); } mode; message { uint32 channels; audio_fmt format; uint32 frequency; uint32 time; } start; Empty stop; AudioVolume volume; AudioMute mute; message { uint32 latency_ms; } latency; }; channel RecordChannel : BaseChannel { server: message { uint32 channels; audio_fmt format; uint32 frequency; } start = 101; Empty stop; AudioVolume volume; AudioMute mute; client: message { uint32 time; uint8 data[] @nomarshal @as_ptr(data_size); } @ctype(SpiceMsgcRecordPacket) data = 101; message { uint32 time; audio_data_mode mode; uint8 data[] @as_ptr(data_size); } mode; message { uint32 time; } start_mark; }; enum16 tunnel_service_type { INVALID, GENERIC, IPP, }; enum16 tunnel_ip_type { INVALID, IPv4, }; struct TunnelIpInfo { tunnel_ip_type type; switch (type) { case IPv4: uint8 ipv4[4]; } u; } @ctype(SpiceMsgTunnelIpInfo); channel TunnelChannel : BaseChannel { server: message { uint16 max_num_of_sockets; uint32 max_socket_data_size; } init = 101; message { uint32 service_id; TunnelIpInfo virtual_ip; } service_ip_map; message { uint16 connection_id; uint32 service_id; uint32 tokens; } socket_open; message { uint16 connection_id; } socket_fin; message { uint16 connection_id; } socket_close; message { uint16 connection_id; uint8 data[] @end; } socket_data; message { uint16 connection_id; } socket_closed_ack; message { uint16 connection_id; uint32 num_tokens; } @ctype(SpiceMsgTunnelSocketTokens) socket_token; client: message { tunnel_service_type type; uint32 id; uint32 group; uint32 port; uint8 *name[cstring()] @nocopy; uint8 *description[cstring()] @nocopy; switch (type) { case IPP: TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo); } u; } @ctype(SpiceMsgcTunnelAddGenericService) service_add = 101; message { uint32 id; } @ctype(SpiceMsgcTunnelRemoveService) service_remove; message { uint16 connection_id; uint32 tokens; } socket_open_ack; message { uint16 connection_id; } socket_open_nack; message { uint16 connection_id; } socket_fin; message { uint16 connection_id; } socket_closed; message { uint16 connection_id; } socket_closed_ack; message { uint16 connection_id; uint8 data[] @end; } socket_data; message { uint16 connection_id; uint32 num_tokens; } @ctype(SpiceMsgcTunnelSocketTokens) socket_token; }; 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 data[]; } @ctype(VSCMsgATR); struct VscMessageReaderAdd { int8 *reader_name[] @zero_terminated @nonnull @end @nomarshal; } @ctype(VSCMsgReaderAdd); channel SmartcardChannel : BaseChannel { server: message { vsc_message_type type; uint32 reader_id; uint32 length; uint8 data[] @end; } @ctype(SpiceMsgSmartcard) data = 101; client: 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) data = 101; message { vsc_message_type type; uint32 reader_id; uint32 length; } @ctype(VSCMsgHeader) header = 101; message { uint32 code; } @ctype(VSCMsgError) error = 101; message { uint8 data[]; } @ctype(VSCMsgATR) atr = 101; message { int8 reader_name[] @zero_terminated @nonnull; } @ctype(VSCMsgReaderAdd) reader_add = 101; } @ifdef(USE_SMARTCARD); channel SpicevmcChannel : BaseChannel { server: Data data = 101; client: Data data = 101; }; channel UsbredirChannel : SpicevmcChannel { }; channel PortChannel : SpicevmcChannel { client: message { uint8 event; } event = 201; server: message { uint32 name_size; uint8 *name[name_size] @zero_terminated @marshall @nonnull; uint8 opened; } init = 201; message { uint8 event; } 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; };