1/* built in types: 2 int8, uint8, 16, 32, 64 3*/ 4 5typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4); 6 7/* IDs of the video stream messages. 8 * These IDs are in the interval [0, SPICE_MAX_NUM_STREAMS) 9 */ 10typedef stream_id_t uint32; 11 12struct Point { 13 int32 x; 14 int32 y; 15}; 16 17struct Point16 { 18 int16 x; 19 int16 y; 20}; 21 22struct PointFix { 23 fixed28_4 x; 24 fixed28_4 y; 25}; 26 27struct Rect { 28 int32 top; 29 int32 left; 30 int32 bottom; 31 int32 right; 32}; 33 34struct Transform { 35 uint32 t00; 36 uint32 t01; 37 uint32 t02; 38 uint32 t10; 39 uint32 t11; 40 uint32 t12; 41}; 42 43enum32 link_err { 44 OK, 45 ERROR, 46 INVALID_MAGIC, 47 INVALID_DATA, 48 VERSION_MISMATCH, 49 NEED_SECURED, 50 NEED_UNSECURED, 51 PERMISSION_DENIED, 52 BAD_CONNECTION_ID, 53 CHANNEL_NOT_AVAILABLE 54}; 55 56enum32 warn_code { 57 WARN_GENERAL 58} @prefix(SPICE_); 59 60enum32 info_code { 61 INFO_GENERAL 62} @prefix(SPICE_); 63 64flags32 migrate_flags { 65 NEED_FLUSH, 66 NEED_DATA_TRANSFER 67} @prefix(SPICE_MIGRATE_); 68 69flags32 composite_flags { 70 OP0, OP1, OP2, OP3, OP4, OP5, OP6, OP7, 71 SRC_FILTER0, SRC_FILTER1, SRC_FILTER2, 72 MASK_FILTER0, MASK_FITLER1, MASK_FILTER2, 73 74 SRC_REPEAT0, SRC_REPEAT1, 75 MASK_REPEAT0, MASK_REPEAT1, 76 COMPONENT_ALPHA, 77 78 HAS_MASK, 79 HAS_SRC_TRANSFORM, 80 HAS_MASK_TRANSFORM, 81 82 /* These are used to override the formats given in the images. For 83 * example, if the mask image has format a8r8g8b8, but MASK_OPAQUE 84 * is set, the image should be treated as if it were x8r8g8b8 85 */ 86 SOURCE_OPAQUE, 87 MASK_OPAQUE, 88 DEST_OPAQUE, 89} @prefix(SPICE_COMPOSITE_); 90 91enum32 notify_severity { 92 INFO, 93 WARN, 94 ERROR, 95}; 96 97enum32 notify_visibility { 98 LOW, 99 MEDIUM, 100 HIGH, 101}; 102 103flags16 mouse_mode { 104 SERVER, 105 CLIENT, 106}; 107 108message Empty { 109} @declare; 110 111message Data { 112 uint8 data[] @end; 113} @nocopy @declare; 114 115enum8 data_compression_type { 116 NONE, 117 LZ4, 118}; 119 120struct EmptyStructure { 121}; 122 123message CompressedData { 124 data_compression_type type; 125 switch (type) { 126 /* we cannot use !NONE (works only with flags) */ 127 case NONE: 128 /* due to the way cases are defined after NONE we must have something */ 129 /* due to a bug we cannot use @virtual to write 0 to compressed_size */ 130 EmptyStructure empty; 131 default: 132 uint32 uncompressed_size; 133 } u @anon; 134 uint8 compressed_data[] @as_ptr(compressed_size); 135} @ctype(SpiceMsgCompressedData); 136 137struct ChannelWait { 138 uint8 channel_type; 139 uint8 channel_id; 140 uint64 message_serial; 141} @ctype(SpiceWaitForChannel) @declare; 142 143channel BaseChannel { 144 server: 145 message { 146 migrate_flags flags; 147 } @declare migrate; 148 149 Data migrate_data; 150 151 message { 152 uint32 generation; 153 uint32 window; 154 } @declare set_ack; 155 156 message { 157 uint32 id; 158 uint64 timestamp; 159 uint8 data[] @as_ptr(data_len); 160 } @declare ping; 161 162 message { 163 uint8 wait_count; 164 ChannelWait wait_list[wait_count] @end; 165 } @declare wait_for_channels; 166 167 message { 168 uint64 time_stamp; 169 link_err reason; 170 } @ctype(SpiceMsgDisconnect) @declare disconnecting; 171 172 message { 173 uint64 time_stamp; 174 notify_severity severity; 175 notify_visibility visibilty; 176 uint32 what; /* error_code/warn_code/info_code */ 177 uint32 message_len; 178 uint8 message[message_len] @end @nomarshal; 179 } @declare notify; 180 181 Data list; /* the msg body is SpiceSubMessageList */ 182 183 Empty base_last = 100; 184 185 client: 186 message { 187 uint32 generation; 188 } @declare ack_sync; 189 190 Empty ack; 191 192 message { 193 uint32 id; 194 uint64 timestamp; 195 } @ctype(SpiceMsgPing) pong; 196 197 Empty migrate_flush_mark; 198 199 Data migrate_data; 200 201 message { 202 uint64 time_stamp; 203 link_err reason; 204 } @ctype(SpiceMsgDisconnect) disconnecting; 205}; 206 207struct ChannelId { 208 uint8 type; 209 uint8 id; 210} @declare; 211 212struct DstInfo { 213 uint16 port; 214 uint16 sport; 215 uint32 host_size; 216 uint8 *host_data[host_size] @zero_terminated @marshall @nonnull; 217 uint32 cert_subject_size; 218 uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall; 219} @ctype(SpiceMigrationDstInfo) @declare; 220 221channel MainChannel : BaseChannel { 222 server: 223 message { 224 DstInfo dst_info; 225 } @ctype(SpiceMsgMainMigrationBegin) @declare migrate_begin = 101; 226 227 Empty migrate_cancel; 228 229 message { 230 uint32 session_id; 231 uint32 display_channels_hint; 232 uint32 supported_mouse_modes; 233 uint32 current_mouse_mode; 234 uint32 agent_connected; 235 uint32 agent_tokens; 236 uint32 multi_media_time; 237 uint32 ram_hint; 238 } @declare init; 239 240 message { 241 uint32 num_of_channels; 242 ChannelId channels[num_of_channels] @end; 243 } @ctype(SpiceMsgChannels) @declare channels_list; 244 245 message { 246 mouse_mode supported_modes; 247 mouse_mode current_mode @unique_flag; 248 } @declare mouse_mode; 249 250 message { 251 uint32 time; 252 } @ctype(SpiceMsgMainMultiMediaTime) @declare multi_media_time; 253 254 Empty agent_connected; 255 256 message { 257 link_err error_code; 258 } @ctype(SpiceMsgMainAgentDisconnect) @declare agent_disconnected; 259 260 Data agent_data; 261 262 message { 263 uint32 num_tokens; 264 } @ctype(SpiceMsgMainAgentTokens) @declare agent_token; 265 266 message { 267 uint16 port; 268 uint16 sport; 269 uint32 host_size; 270 uint8 *host_data[host_size] @zero_terminated @marshall; 271 uint32 cert_subject_size; 272 uint8 *cert_subject_data[cert_subject_size] @zero_terminated @marshall; 273 } @ctype(SpiceMsgMainMigrationSwitchHost) @declare migrate_switch_host; 274 275 Empty migrate_end; 276 277 message { 278 uint32 name_len; 279 uint8 name[name_len] @end; 280 } @declare name; 281 282 message { 283 uint8 uuid[16]; 284 } @declare uuid; 285 286 message { 287 uint32 num_tokens; 288 } @declare agent_connected_tokens; 289 290 message { 291 DstInfo dst_info; 292 uint32 src_mig_version; 293 } @declare migrate_begin_seamless; 294 295 Empty migrate_dst_seamless_ack; 296 Empty migrate_dst_seamless_nack; 297 298 client: 299 message { 300 uint64 cache_size; 301 } @ctype(SpiceMsgcClientInfo) @declare client_info = 101; 302 303 Empty migrate_connected; 304 305 Empty migrate_connect_error; 306 307 Empty attach_channels; 308 309 message { 310 mouse_mode mode; 311 } @declare mouse_mode_request; 312 313 message { 314 uint32 num_tokens; 315 } @ctype(SpiceMsgMainAgentTokens) @declare agent_start; 316 317 Data agent_data; 318 319 message { 320 uint32 num_tokens; 321 } @ctype(SpiceMsgMainAgentTokens) @declare agent_token; 322 323 Empty migrate_end; 324 325 message { 326 uint32 src_version; 327 } @declare migrate_dst_do_seamless; 328 329 Empty migrate_connected_seamless; 330 331 Data quality_indicator; 332}; 333 334enum8 clip_type { 335 NONE, 336 RECTS 337}; 338 339flags8 path_flags { /* TODO: C enum names changes */ 340 BEGIN = 0, 341 END = 1, 342 CLOSE = 3, 343 BEZIER = 4, 344} @prefix(SPICE_PATH_); 345 346enum8 video_codec_type { 347 MJPEG = 1, 348 VP8, 349 H264, 350 VP9, 351 H265, 352}; 353 354flags8 stream_flags { 355 TOP_DOWN = 0, 356}; 357 358enum8 brush_type { 359 NONE, 360 SOLID, 361 PATTERN, 362}; 363 364flags8 mask_flags { 365 INVERS, 366}; 367 368enum8 image_type { 369 BITMAP, 370 QUIC, 371 RESERVED, 372 LZ_PLT = 100, 373 LZ_RGB, 374 GLZ_RGB, 375 FROM_CACHE, 376 SURFACE, 377 JPEG, 378 FROM_CACHE_LOSSLESS, 379 ZLIB_GLZ_RGB, 380 JPEG_ALPHA, 381 LZ4, 382}; 383 384enum8 image_compression { 385 INVALID = 0, 386 OFF, 387 AUTO_GLZ, 388 AUTO_LZ, 389 QUIC, 390 GLZ, 391 LZ, 392 LZ4, 393}; 394 395flags8 image_flags { 396 CACHE_ME, 397 HIGH_BITS_SET, 398 CACHE_REPLACE_ME, 399}; 400 401enum8 bitmap_fmt { 402 INVALID, 403 1BIT_LE, 404 1BIT_BE, 405 4BIT_LE, 406 4BIT_BE, 407 8BIT /* 8bit indexed mode */, 408 16BIT, /* 0555 mode */ 409 24BIT /* 3 byte, brg */, 410 32BIT /* 4 byte, xrgb in little endian format */, 411 RGBA /* 4 byte, argb in little endian format */, 412 8BIT_A /* 1 byte, alpha */ 413}; 414 415flags8 bitmap_flags { 416 PAL_CACHE_ME, 417 PAL_FROM_CACHE, 418 TOP_DOWN, 419}; 420 421flags8 jpeg_alpha_flags { 422 TOP_DOWN, 423}; 424 425enum8 image_scale_mode { 426 INTERPOLATE, 427 NEAREST, 428}; 429 430flags16 ropd { 431 INVERS_SRC, 432 INVERS_BRUSH, 433 INVERS_DEST, 434 OP_PUT, 435 OP_OR, 436 OP_AND, 437 OP_XOR, 438 OP_BLACKNESS, 439 OP_WHITENESS, 440 OP_INVERS, 441 INVERS_RES, 442}; 443 444/* This *must* remain with values identical to api/winddi.h 445 LA_STYLED == 0x8 (log_2)=> 3 446 LA_STARTGAP == 0x4 (log_2)=> 2 447 This is used by the windows driver. 448 */ 449flags8 line_flags { 450 STYLED = 3, 451 START_WITH_GAP = 2, 452}; 453 454flags8 string_flags { 455 RASTER_A1, 456 RASTER_A4, 457 RASTER_A8, 458 RASTER_TOP_DOWN, 459}; 460 461flags32 surface_flags { 462 /* Adding flags requires some caps check, since old clients only 463 treat the value as an enum and not as a flag (flag == PRIMARY). 464 Considering this was fixed by commit 465 5b6e3d1c16457c926322ce28d341af2e8d39efb5 in Aug 21 2013 is safe 466 to assume that if capabilities include SPICE_DISPLAY_CAP_MULTI_CODEC 467 we can use any flags */ 468 PRIMARY, 469 /* The surface will be streamed entirely. This means that only 470 stream commands will be received and the stream will cover the 471 entire surface. This flag can be safely ignored and is intended 472 as an hint for the client */ 473 STREAMING_MODE, 474}; 475 476enum32 surface_fmt { 477 INVALID, 478 1_A = 1, 479 8_A = 8, 480 16_555 = 16 , 481 16_565 = 80, 482 32_xRGB = 32, 483 32_ARGB = 96 484}; 485 486flags8 alpha_flags { 487 DEST_HAS_ALPHA, 488 SRC_SURFACE_HAS_ALPHA 489}; 490 491enum8 resource_type { 492 INVALID, 493 PIXMAP 494} @prefix(SPICE_RES_TYPE_); 495 496struct ClipRects { 497 uint32 num_rects; 498 Rect rects[num_rects] @end; 499}; 500 501struct PathSegment { 502 path_flags flags; 503 uint32 count; 504 PointFix points[count] @end; 505} @ctype(SpicePathSeg); 506 507struct Path { 508 uint32 num_segments; 509 PathSegment segments[num_segments] @ptr_array; 510}; 511 512struct Clip { 513 clip_type type; 514 switch (type) { 515 case RECTS: 516 ClipRects rects @outvar(cliprects) @to_ptr; 517 } u @anon; 518}; 519 520struct DisplayBase { 521 uint32 surface_id; 522 Rect box; 523 Clip clip; 524} @ctype(SpiceMsgDisplayBase) @declare; 525 526struct ResourceID { 527 uint8 type; /* resource_type */ 528 uint64 id; 529} @declare; 530 531struct WaitForChannel { 532 uint8 channel_type; 533 uint8 channel_id; 534 uint64 message_serial; 535} @declare; 536 537struct Palette { 538 uint64 unique; 539 uint16 num_ents; 540 uint32 ents[num_ents] @end; 541}; 542 543struct BitmapData { 544 bitmap_fmt format; 545 bitmap_flags flags; 546 uint32 x; 547 uint32 y; 548 uint32 stride; 549 switch (flags) { 550 case PAL_FROM_CACHE: 551 uint64 palette_id; 552 default: 553 Palette *palette @outvar(bitmap); 554 } pal @anon; 555 uint8 data[image_size(8, stride, y)] @chunk @nomarshal; 556} @ctype(SpiceBitmap); 557 558struct BinaryData { 559 uint32 data_size; 560 uint8 data[data_size] @nomarshal @chunk; 561} @ctype(SpiceQUICData); 562 563struct LZPLTData { 564 bitmap_flags flags; 565 uint32 data_size; 566 switch (flags) { 567 case PAL_FROM_CACHE: 568 uint64 palette_id; 569 default: 570 Palette *palette @nonnull @outvar(lzplt); 571 } pal @anon; 572 uint8 data[data_size] @nomarshal @chunk; 573}; 574 575struct ZlibGlzRGBData { 576 uint32 glz_data_size; 577 uint32 data_size; 578 uint8 data[data_size] @nomarshal @chunk; 579} @ctype(SpiceZlibGlzRGBData); 580 581struct JPEGAlphaData { 582 jpeg_alpha_flags flags; 583 uint32 jpeg_size; 584 uint32 data_size; 585 uint8 data[data_size] @nomarshal @chunk; 586} @ctype(SpiceJPEGAlphaData); 587 588struct Surface { 589 uint32 surface_id; 590}; 591 592 593struct Image { 594 struct ImageDescriptor { 595 uint64 id; 596 image_type type; 597 image_flags flags; 598 uint32 width; 599 uint32 height; 600 } descriptor; 601 602 switch (descriptor.type) { 603 case BITMAP: 604 BitmapData bitmap; 605 case QUIC: 606 BinaryData quic; 607 case LZ_RGB: 608 case GLZ_RGB: 609 BinaryData lz_rgb; 610 case JPEG: 611 BinaryData jpeg; 612 case LZ4: 613 BinaryData lz4; 614 case LZ_PLT: 615 LZPLTData lz_plt; 616 case ZLIB_GLZ_RGB: 617 ZlibGlzRGBData zlib_glz; 618 case JPEG_ALPHA: 619 JPEGAlphaData jpeg_alpha; 620 case SURFACE: 621 Surface surface; 622 } u; 623}; 624 625struct Pattern { 626 Image *pat @nonnull; 627 Point pos; 628}; 629 630struct Brush { 631 brush_type type; 632 switch (type) { 633 case SOLID: 634 uint32 color; 635 case PATTERN: 636 Pattern pattern; 637 } u; 638}; 639 640struct QMask { 641 mask_flags flags; 642 Point pos; 643 Image *bitmap; 644}; 645 646struct LineAttr { 647 line_flags flags; 648 switch (flags) { 649 case STYLED: 650 uint8 style_nseg; 651 } u1 @anon; 652 switch (flags) { 653 case STYLED: 654 fixed28_4 *style[style_nseg]; 655 } u2 @anon; 656}; 657 658struct RasterGlyphA1 { 659 Point render_pos; 660 Point glyph_origin; 661 uint16 width; 662 uint16 height; 663 uint8 data[image_size(1, width, height)] @end; 664} @ctype(SpiceRasterGlyph); 665 666struct RasterGlyphA4 { 667 Point render_pos; 668 Point glyph_origin; 669 uint16 width; 670 uint16 height; 671 uint8 data[image_size(4, width, height)] @end; 672} @ctype(SpiceRasterGlyph); 673 674struct RasterGlyphA8 { 675 Point render_pos; 676 Point glyph_origin; 677 uint16 width; 678 uint16 height; 679 uint8 data[image_size(8, width, height)] @end; 680} @ctype(SpiceRasterGlyph); 681 682struct String { 683 uint16 length; 684 string_flags flags; /* Special: Only one of a1/a4/a8 set */ 685 switch (flags) { 686 case RASTER_A1: 687 RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; 688 case RASTER_A4: 689 RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; 690 case RASTER_A8: 691 RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph) @ptr_array; 692 } u @anon; 693}; 694 695struct StreamDataHeader { 696 stream_id_t id; 697 uint32 multi_media_time; 698} @declare; 699 700struct Head { 701 uint32 monitor_id; 702 uint32 surface_id; 703 uint32 width; 704 uint32 height; 705 uint32 x; 706 uint32 y; 707 uint32 flags; 708} @declare; 709 710flags32 gl_scanout_flags { 711 Y0TOP 712}; 713 714channel DisplayChannel : BaseChannel { 715 server: 716 message { 717 uint32 x_res; 718 uint32 y_res; 719 uint32 bits; 720 } @declare mode = 101; 721 722 Empty mark; 723 Empty reset; 724 message { 725 DisplayBase base; 726 Point src_pos; 727 } @declare copy_bits; 728 729 message { 730 uint16 count; 731 ResourceID resources[count] @end; 732 } @ctype(SpiceResourceList) @declare inval_list; 733 734 /* This message is used to invalidate the complete image cache 735 * on the client. 736 * Due to synchronization for GLZ images we must make sure 737 * that messages related to cached images on other channels 738 * are processed so we send a list of channels with respective 739 * message serials to wait for. 740 */ 741 message { 742 uint8 wait_count; 743 WaitForChannel wait_list[wait_count] @end; 744 } @ctype(SpiceMsgWaitForChannels) @declare inval_all_pixmaps; 745 746 message { 747 uint64 id; 748 } @ctype(SpiceMsgDisplayInvalOne) @declare inval_palette; 749 750 Empty inval_all_palettes; 751 752 message { 753 uint32 surface_id; 754 stream_id_t id; 755 stream_flags flags; 756 video_codec_type codec_type; 757 uint64 stamp; 758 uint32 stream_width; 759 uint32 stream_height; 760 uint32 src_width; 761 uint32 src_height; 762 Rect dest; 763 Clip clip; 764 } @declare stream_create = 122; 765 766 message { 767 StreamDataHeader base; 768 uint32 data_size; 769 uint8 data[data_size] @end @nomarshal; 770 } @declare stream_data; 771 772 message { 773 stream_id_t id; 774 Clip clip; 775 } @declare stream_clip; 776 777 message { 778 stream_id_t id; 779 } @declare stream_destroy; 780 781 Empty stream_destroy_all; 782 783 message { 784 DisplayBase base; 785 struct Fill { 786 Brush brush @outvar(brush); 787 ropd rop_descriptor; 788 QMask mask @outvar(mask); 789 } data; 790 } @declare draw_fill = 302; 791 792 message { 793 DisplayBase base; 794 struct Opaque { 795 Image *src_bitmap; 796 Rect src_area; 797 Brush brush; 798 ropd rop_descriptor; 799 image_scale_mode scale_mode; 800 QMask mask @outvar(mask); 801 } data; 802 } @declare draw_opaque; 803 804 message { 805 DisplayBase base; 806 struct Copy { 807 Image *src_bitmap; 808 Rect src_area; 809 ropd rop_descriptor; 810 image_scale_mode scale_mode; 811 QMask mask @outvar(mask); 812 } data; 813 } @declare draw_copy; 814 815 message { 816 DisplayBase base; 817 struct Blend { 818 Image *src_bitmap; 819 Rect src_area; 820 ropd rop_descriptor; 821 image_scale_mode scale_mode; 822 QMask mask @outvar(mask); 823 } @ctype(SpiceCopy) data; 824 } @ctype(SpiceMsgDisplayDrawCopy) draw_blend; 825 826 message { 827 DisplayBase base; 828 struct Blackness { 829 QMask mask @outvar(mask); 830 } data; 831 } @declare draw_blackness; 832 833 message { 834 DisplayBase base; 835 struct Whiteness { 836 QMask mask @outvar(mask); 837 } data; 838 } @declare draw_whiteness; 839 840 message { 841 DisplayBase base; 842 struct Invers { 843 QMask mask @outvar(mask); 844 } data; 845 } @declare draw_invers; 846 847 message { 848 DisplayBase base; 849 struct Rop3 { 850 Image *src_bitmap; 851 Rect src_area; 852 Brush brush; 853 uint8 rop3; 854 image_scale_mode scale_mode; 855 QMask mask @outvar(mask); 856 } data; 857 } @declare draw_rop3; 858 859 message { 860 DisplayBase base; 861 struct Stroke { 862 Path *path @marshall @nonnull; 863 LineAttr attr; 864 Brush brush; 865 uint16 fore_mode; 866 uint16 back_mode; 867 } data; 868 } @declare draw_stroke; 869 870 message { 871 DisplayBase base; 872 struct Text { 873 String *str @marshall @nonnull; 874 Rect back_area; 875 Brush fore_brush @outvar(fore_brush); 876 Brush back_brush @outvar(back_brush); 877 uint16 fore_mode; 878 uint16 back_mode; 879 } data; 880 } @declare draw_text; 881 882 message { 883 DisplayBase base; 884 struct Transparent { 885 Image *src_bitmap; 886 Rect src_area; 887 uint32 src_color; 888 uint32 true_color; 889 } data; 890 } @declare draw_transparent; 891 892 message { 893 DisplayBase base; 894 struct AlphaBlend { 895 alpha_flags alpha_flags; 896 uint8 alpha; 897 Image *src_bitmap; 898 Rect src_area; 899 } data; 900 } @declare draw_alpha_blend; 901 902 message { 903 uint32 surface_id; 904 uint32 width; 905 uint32 height; 906 surface_fmt format; 907 surface_flags flags; 908 } @ctype(SpiceMsgSurfaceCreate) @declare surface_create; 909 910 message { 911 uint32 surface_id; 912 } @ctype(SpiceMsgSurfaceDestroy) @declare surface_destroy; 913 914 message { 915 StreamDataHeader base; 916 uint32 width; 917 uint32 height; 918 Rect dest; 919 uint32 data_size; 920 uint8 data[data_size] @end @nomarshal; 921 } @declare stream_data_sized; 922 923 message { 924 uint16 count; 925 uint16 max_allowed; 926 Head heads[count] @end; 927 } @declare monitors_config; 928 929 message { 930 DisplayBase base; 931 struct Composite { 932 composite_flags flags; 933 Image *src_bitmap; 934 switch (flags) { 935 case HAS_MASK: 936 Image *mask_bitmap; 937 } a @anon; 938 switch (flags) { 939 case HAS_SRC_TRANSFORM: 940 Transform src_transform; 941 } b @anon; 942 switch (flags) { 943 case HAS_MASK_TRANSFORM: 944 Transform mask_transform; 945 } c @anon; 946 Point16 src_origin; 947 Point16 mask_origin; 948 } data; 949 } @declare draw_composite; 950 951 message { 952 stream_id_t stream_id; 953 uint32 unique_id; 954 uint32 max_window_size; 955 uint32 timeout_ms; 956 } @declare stream_activate_report; 957 958 message { 959 unix_fd drm_dma_buf_fd; 960 uint32 width; 961 uint32 height; 962 uint32 stride; 963 /* specifies the format of drm_dma_buf_fd defined in drm_fourcc.h */ 964 uint32 drm_fourcc_format; 965 gl_scanout_flags flags; 966 } @declare gl_scanout_unix; 967 968 message { 969 uint32 x; 970 uint32 y; 971 uint32 w; 972 uint32 h; 973 } @declare gl_draw; 974 975 Data quality_indicator; 976 client: 977 message { 978 uint8 pixmap_cache_id; 979 int64 pixmap_cache_size; //in pixels 980 uint8 glz_dictionary_id; 981 int32 glz_dictionary_window_size; // in pixels 982 } @declare init = 101; 983 984 message { 985 stream_id_t stream_id; 986 uint32 unique_id; 987 // the mm_time of the first frame included in the report 988 uint32 start_frame_mm_time; 989 // the mm_time of the last frame included in the report 990 uint32 end_frame_mm_time; 991 // the number of frames that reached the client during the time the 992 // report is referring to 993 // A special case is when num_frames == 0 and num_drops == 994 // 0xffffffffu, this is used in the client to communicate that 995 // the stream is not supported or that the client was not able 996 // to decode it 997 uint32 num_frames; 998 // the part of the above frames that were dropped by the client due 999 // to late arrival time 1000 uint32 num_drops; 1001 // end_frame_mm_time - client_mm_time 1002 int32 last_frame_delay; 1003 // the latency of the audio playback 1004 // If there is no audio playback, set it to 0xffffffffu 1005 uint32 audio_delay; 1006 } @declare stream_report; 1007 1008 message { 1009 image_compression image_compression; 1010 } @declare preferred_compression; 1011 1012 message { 1013 } @declare gl_draw_done; 1014 1015 message { 1016 uint8 num_of_codecs; 1017 video_codec_type codecs[num_of_codecs] @end; 1018 } @declare preferred_video_codec_type; 1019}; 1020 1021flags16 keyboard_modifier_flags { 1022 SCROLL_LOCK, 1023 NUM_LOCK, 1024 CAPS_LOCK 1025}; 1026 1027enum8 mouse_button { 1028 INVALID, 1029 LEFT, 1030 MIDDLE, 1031 RIGHT, 1032 UP, 1033 DOWN, 1034 SIDE, 1035 EXTRA, 1036}; 1037 1038flags16 mouse_button_mask { 1039 LEFT, 1040 MIDDLE, 1041 RIGHT, 1042 UP, 1043 DOWN, 1044 SIDE, 1045 EXTRA, 1046}; 1047 1048channel InputsChannel : BaseChannel { 1049 client: 1050 message { 1051 uint32 code; 1052 } @ctype(SpiceMsgcKeyDown) @declare key_down = 101; 1053 1054 message { 1055 uint32 code; 1056 } @ctype(SpiceMsgcKeyUp) @declare key_up; 1057 1058 message { 1059 keyboard_modifier_flags modifiers; 1060 } @ctype(SpiceMsgcKeyModifiers) @declare key_modifiers; 1061 1062 Data key_scancode; 1063 1064 message { 1065 int32 dx; 1066 int32 dy; 1067 mouse_button_mask buttons_state; 1068 } @ctype(SpiceMsgcMouseMotion) @declare mouse_motion = 111; 1069 1070 message { 1071 uint32 x; 1072 uint32 y; 1073 mouse_button_mask buttons_state; 1074 uint8 display_id; 1075 } @ctype(SpiceMsgcMousePosition) @declare mouse_position; 1076 1077 message { 1078 mouse_button button; 1079 mouse_button_mask buttons_state; 1080 } @ctype(SpiceMsgcMousePress) @declare mouse_press; 1081 1082 message { 1083 mouse_button button; 1084 mouse_button_mask buttons_state; 1085 } @ctype(SpiceMsgcMouseRelease) @declare mouse_release; 1086 1087 server: 1088 message { 1089 keyboard_modifier_flags keyboard_modifiers; 1090 } @declare init = 101; 1091 1092 message { 1093 keyboard_modifier_flags modifiers; 1094 } @declare key_modifiers; 1095 1096 Empty mouse_motion_ack = 111; 1097}; 1098 1099enum8 cursor_type { 1100 ALPHA, 1101 MONO, 1102 COLOR4, 1103 COLOR8, 1104 COLOR16, 1105 COLOR24, 1106 COLOR32, 1107}; 1108 1109flags16 cursor_flags { 1110 NONE, /* Means no cursor */ 1111 CACHE_ME, 1112 FROM_CACHE, 1113}; 1114 1115struct CursorHeader { 1116 uint64 unique; 1117 cursor_type type; 1118 uint16 width; 1119 uint16 height; 1120 uint16 hot_spot_x; 1121 uint16 hot_spot_y; 1122}; 1123 1124struct Cursor { 1125 cursor_flags flags; 1126 switch (flags) { 1127 case !NONE: 1128 CursorHeader header; 1129 } u @anon; 1130 uint8 data[] @as_ptr(data_size); 1131} @declare; 1132 1133channel CursorChannel : BaseChannel { 1134 server: 1135 message { 1136 Point16 position; 1137 uint16 trail_length; 1138 uint16 trail_frequency; 1139 uint8 visible; 1140 Cursor cursor; 1141 } @declare init = 101; 1142 1143 Empty reset; 1144 1145 message { 1146 Point16 position; 1147 uint8 visible; 1148 Cursor cursor; 1149 } @declare set; 1150 1151 message { 1152 Point16 position; 1153 } @declare move; 1154 1155 Empty hide; 1156 1157 message { 1158 uint16 length; 1159 uint16 frequency; 1160 } @declare trail; 1161 1162 message { 1163 uint64 id; 1164 } @ctype(SpiceMsgDisplayInvalOne) @declare inval_one; 1165 1166 Empty inval_all; 1167}; 1168 1169enum16 audio_data_mode { 1170 INVALID, 1171 RAW, 1172 CELT_0_5_1 @deprecated, 1173 OPUS, 1174}; 1175 1176enum16 audio_fmt { 1177 INVALID, 1178 S16, 1179}; 1180 1181message AudioVolume { 1182 uint8 nchannels; 1183 uint16 volume[nchannels] @end; 1184} @declare; 1185 1186message AudioMute { 1187 uint8 mute; 1188} @declare; 1189 1190channel PlaybackChannel : BaseChannel { 1191 server: 1192 message { 1193 uint32 time; 1194 uint8 data[] @as_ptr(data_size); 1195 } @ctype(SpiceMsgPlaybackPacket) @declare data = 101; 1196 1197 message { 1198 uint32 time; 1199 audio_data_mode mode; 1200 uint8 data[] @as_ptr(data_size); 1201 } @declare mode; 1202 1203 message { 1204 uint32 channels; 1205 audio_fmt format; 1206 uint32 frequency; 1207 uint32 time; 1208 } @declare start; 1209 1210 Empty stop; 1211 AudioVolume volume; 1212 AudioMute mute; 1213 1214 message { 1215 uint32 latency_ms; 1216 } @declare latency; 1217}; 1218 1219channel RecordChannel : BaseChannel { 1220 server: 1221 message { 1222 uint32 channels; 1223 audio_fmt format; 1224 uint32 frequency; 1225 } @declare start = 101; 1226 1227 Empty stop; 1228 AudioVolume volume; 1229 AudioMute mute; 1230 client: 1231 message { 1232 uint32 time; 1233 uint8 data[] @nomarshal @as_ptr(data_size); 1234 } @ctype(SpiceMsgPlaybackPacket) @declare data = 101; 1235 1236 message { 1237 uint32 time; 1238 audio_data_mode mode; 1239 uint8 data[] @as_ptr(data_size); 1240 } @ctype(SpiceMsgPlaybackMode) @declare mode; 1241 1242 message { 1243 uint32 time; 1244 } @declare start_mark; 1245}; 1246 1247channel TunnelChannel { 1248}; 1249 1250enum32 vsc_message_type { 1251 Init = 1, 1252 Error, 1253 ReaderAdd, 1254 ReaderRemove, 1255 ATR, 1256 CardRemove, 1257 APDU, 1258 Flush, 1259 FlushComplete 1260}; 1261 1262struct VscMessageHeader { 1263 vsc_message_type type; 1264 uint32 reader_id; 1265 uint32 length; 1266} @ctype(VSCMsgHeader); 1267 1268struct VscMessageError { 1269 uint32 code; 1270} @ctype(VSCMsgError); 1271 1272struct VscMessageAPDU { 1273 uint8 data[]; 1274} @ctype(VSCMsgAPDU); 1275 1276struct VscMessageATR { 1277 uint8 atr[]; 1278} @ctype(VSCMsgATR); 1279 1280struct VscMessageReaderAdd { 1281 int8 *name[] @zero_terminated @nonnull @end @nomarshal; 1282} @ctype(VSCMsgReaderAdd); 1283 1284channel SmartcardChannel : BaseChannel { 1285 server: 1286 message { 1287 vsc_message_type type; 1288 uint32 reader_id; 1289 uint32 length; 1290 uint8 data[length] @end @nomarshal; 1291 } @ctype(SpiceMsgSmartcard) data = 101; 1292 1293 client: 1294/* Some of the following messages are duplicated, the protocol 1295 * definition was broken. Messages, as you can see have same ID. 1296 * Also code was not used and didn't compile correctly. 1297 * Keeping in the hope could be useful in the future. 1298 */ 1299/* 1300 message { 1301 VscMessageHeader header; 1302 switch (header.type) { 1303 case ReaderAdd: 1304 VscMessageReaderAdd add; 1305 case ATR: 1306 case APDU: 1307 VscMessageATR atr_data; 1308 case Error: 1309 VscMessageError error; 1310 } u @anon; 1311 } @ctype(SpiceMsgcSmartcard) old_data = 101; 1312*/ 1313 message { 1314 vsc_message_type type; 1315 uint32 reader_id; 1316 uint32 length; 1317 uint8 data[length] @end @nomarshal; 1318 } @ctype(VSCMsgHeader) data = 101; 1319/* See comment on client data message above */ 1320/* 1321 message { 1322 uint32 code; 1323 } @ctype(VSCMsgError) error = 101; 1324 1325 message { 1326 uint8 data[]; 1327 } @ctype(VSCMsgATR) atr = 101; 1328 1329 message { 1330 int8 name[] @zero_terminated @nonnull; 1331 } @ctype(VSCMsgReaderAdd) reader_add = 101; 1332*/ 1333} @ifdef(USE_SMARTCARD); 1334 1335channel SpicevmcChannel : BaseChannel { 1336server: 1337 Data data = 101; 1338 CompressedData compressed_data = 102; 1339client: 1340 Data data = 101; 1341 CompressedData compressed_data = 102; 1342}; 1343 1344channel UsbredirChannel : SpicevmcChannel { 1345}; 1346 1347channel PortChannel : SpicevmcChannel { 1348 client: 1349 message { 1350 uint8 event; 1351 } @declare event = 201; 1352 server: 1353 message { 1354 uint32 name_size; 1355 uint8 *name[name_size] @zero_terminated @marshall @nonnull; 1356 uint8 opened; 1357 } @declare init = 201; 1358 message { 1359 uint8 event; 1360 } @declare event; 1361}; 1362 1363channel WebDAVChannel : PortChannel { 1364}; 1365 1366protocol Spice { 1367 MainChannel main = 1; 1368 DisplayChannel display; 1369 InputsChannel inputs; 1370 CursorChannel cursor; 1371 PlaybackChannel playback; 1372 RecordChannel record; 1373 TunnelChannel tunnel; 1374 SmartcardChannel smartcard; 1375 UsbredirChannel usbredir; 1376 PortChannel port; 1377 WebDAVChannel webdav; 1378}; 1379