Lines Matching +full:- +full:- +full:-
5 #include "qemu/error-report.h"
8 #include "hw/qdev-core.h"
15 #include "qapi/qapi-types-char.h"
16 #include "qapi/qapi-types-ui.h"
65 #define TYPE_CHARDEV_QEMU_VDAGENT "chardev-qemu-vdagent"
70 /* ------------------------------------------------------------------ */
74 [VD_AGENT_CAP_MOUSE_STATE] = "mouse-state",
75 [VD_AGENT_CAP_MONITORS_CONFIG] = "monitors-config",
78 [VD_AGENT_CAP_DISPLAY_CONFIG] = "display-config",
79 [VD_AGENT_CAP_CLIPBOARD_BY_DEMAND] = "clipboard-by-demand",
80 [VD_AGENT_CAP_CLIPBOARD_SELECTION] = "clipboard-selection",
81 [VD_AGENT_CAP_SPARSE_MONITORS_CONFIG] = "sparse-monitors-config",
82 [VD_AGENT_CAP_GUEST_LINEEND_LF] = "guest-lineend-lf",
83 [VD_AGENT_CAP_GUEST_LINEEND_CRLF] = "guest-lineend-crlf",
84 [VD_AGENT_CAP_MAX_CLIPBOARD] = "max-clipboard",
85 [VD_AGENT_CAP_AUDIO_VOLUME_SYNC] = "audio-volume-sync",
86 [VD_AGENT_CAP_MONITORS_CONFIG_POSITION] = "monitors-config-position",
87 [VD_AGENT_CAP_FILE_XFER_DISABLED] = "file-xfer-disabled",
88 [VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS] = "file-xfer-detailed-errors",
89 [VD_AGENT_CAP_GRAPHICS_DEVICE_INFO] = "graphics-device-info",
91 [VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB] = "clipboard-no-release-on-regrab",
92 [VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL] = "clipboard-grab-serial",
97 [VD_AGENT_MOUSE_STATE] = "mouse-state",
98 [VD_AGENT_MONITORS_CONFIG] = "monitors-config",
101 [VD_AGENT_DISPLAY_CONFIG] = "display-config",
102 [VD_AGENT_ANNOUNCE_CAPABILITIES] = "announce-capabilities",
103 [VD_AGENT_CLIPBOARD_GRAB] = "clipboard-grab",
104 [VD_AGENT_CLIPBOARD_REQUEST] = "clipboard-request",
105 [VD_AGENT_CLIPBOARD_RELEASE] = "clipboard-release",
106 [VD_AGENT_FILE_XFER_START] = "file-xfer-start",
107 [VD_AGENT_FILE_XFER_STATUS] = "file-xfer-status",
108 [VD_AGENT_FILE_XFER_DATA] = "file-xfer-data",
109 [VD_AGENT_CLIENT_DISCONNECTED] = "client-disconnected",
110 [VD_AGENT_MAX_CLIPBOARD] = "max-clipboard",
111 [VD_AGENT_AUDIO_VOLUME_SYNC] = "audio-volume-sync",
112 [VD_AGENT_GRAPHICS_DEVICE_INFO] = "graphics-device-info",
136 /* ------------------------------------------------------------------ */
143 while (vd->outbuf->len) { in vdagent_send_buf()
148 if (len > vd->outbuf->len) { in vdagent_send_buf()
149 len = vd->outbuf->len; in vdagent_send_buf()
151 qemu_chr_be_write(CHARDEV(vd), vd->outbuf->data, len); in vdagent_send_buf()
152 g_byte_array_remove_range(vd->outbuf, 0, len); in vdagent_send_buf()
159 uint32_t msgsize = sizeof(VDAgentMessage) + msg->size; in vdagent_send_msg()
163 trace_vdagent_send(GET_NAME(msg_name, msg->type)); in vdagent_send_msg()
165 msg->protocol = VD_AGENT_PROTOCOL; in vdagent_send_msg()
167 if (vd->outbuf->len + msgsize > VDAGENT_BUFFER_LIMIT) { in vdagent_send_msg()
174 chunk.size = msgsize - msgoff; in vdagent_send_msg()
178 g_byte_array_append(vd->outbuf, (void *)&chunk, sizeof(chunk)); in vdagent_send_msg()
179 g_byte_array_append(vd->outbuf, msgbuf + msgoff, chunk.size); in vdagent_send_msg()
190 VDAgentAnnounceCapabilities *caps = (void *)msg->data; in vdagent_send_caps()
192 msg->type = VD_AGENT_ANNOUNCE_CAPABILITIES; in vdagent_send_caps()
193 msg->size = sizeof(VDAgentAnnounceCapabilities) + sizeof(uint32_t); in vdagent_send_caps()
194 if (vd->mouse) { in vdagent_send_caps()
195 caps->caps[0] |= (1 << VD_AGENT_CAP_MOUSE_STATE); in vdagent_send_caps()
197 if (vd->clipboard) { in vdagent_send_caps()
198 caps->caps[0] |= (1 << VD_AGENT_CAP_CLIPBOARD_BY_DEMAND); in vdagent_send_caps()
199 caps->caps[0] |= (1 << VD_AGENT_CAP_CLIPBOARD_SELECTION); in vdagent_send_caps()
201 caps->caps[0] |= (1 << VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL); in vdagent_send_caps()
205 caps->request = request; in vdagent_send_caps()
209 /* ------------------------------------------------------------------ */
214 return vd->mouse && in have_mouse()
215 (vd->caps & (1 << VD_AGENT_CAP_MOUSE_STATE)); in have_mouse()
222 VDAgentMouseState *mouse = (void *)msg->data; in vdagent_send_mouse()
224 msg->type = VD_AGENT_MOUSE_STATE; in vdagent_send_mouse()
225 msg->size = sizeof(VDAgentMouseState); in vdagent_send_mouse()
227 mouse->x = vd->mouse_x; in vdagent_send_mouse()
228 mouse->y = vd->mouse_y; in vdagent_send_mouse()
229 mouse->buttons = vd->mouse_btn; in vdagent_send_mouse()
230 mouse->display_id = vd->mouse_display; in vdagent_send_mouse()
255 switch (evt->type) { in vdagent_pointer_event()
257 move = evt->u.abs.data; in vdagent_pointer_event()
260 if (move->axis == INPUT_AXIS_X) { in vdagent_pointer_event()
261 vd->mouse_x = qemu_input_scale_axis(move->value, in vdagent_pointer_event()
265 } else if (move->axis == INPUT_AXIS_Y) { in vdagent_pointer_event()
266 vd->mouse_y = qemu_input_scale_axis(move->value, in vdagent_pointer_event()
271 vd->mouse_display = qemu_console_get_index(src); in vdagent_pointer_event()
275 btn = evt->u.btn.data; in vdagent_pointer_event()
276 if (btn->down) { in vdagent_pointer_event()
277 vd->mouse_btn |= bmap[btn->button]; in vdagent_pointer_event()
279 vd->mouse_btn &= ~bmap[btn->button]; in vdagent_pointer_event()
293 if (vd->caps & (1 << VD_AGENT_CAP_MOUSE_STATE)) { in vdagent_pointer_sync()
305 /* ------------------------------------------------------------------ */
310 return vd->clipboard && in have_clipboard()
311 (vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_BY_DEMAND)); in have_clipboard()
316 return vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_SELECTION); in have_selection()
336 uint8_t *s = msg->data; in vdagent_send_clipboard_grab()
337 uint32_t *data = (uint32_t *)msg->data; in vdagent_send_clipboard_grab()
341 *s = info->selection; in vdagent_send_clipboard_grab()
343 msg->size += sizeof(uint32_t); in vdagent_send_clipboard_grab()
344 } else if (info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { in vdagent_send_clipboard_grab()
349 if (vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { in vdagent_send_clipboard_grab()
350 if (!info->has_serial) { in vdagent_send_clipboard_grab()
352 info->serial = vd->last_serial[info->selection]++; in vdagent_send_clipboard_grab()
353 info->has_serial = true; in vdagent_send_clipboard_grab()
355 *data = info->serial; in vdagent_send_clipboard_grab()
357 msg->size += sizeof(uint32_t); in vdagent_send_clipboard_grab()
363 if (type != VD_AGENT_CLIPBOARD_NONE && info->types[q].available) { in vdagent_send_clipboard_grab()
366 msg->size += sizeof(uint32_t); in vdagent_send_clipboard_grab()
370 msg->type = VD_AGENT_CLIPBOARD_GRAB; in vdagent_send_clipboard_grab()
381 uint8_t *s = msg->data; in vdagent_send_clipboard_release()
382 *s = info->selection; in vdagent_send_clipboard_release()
383 msg->size += sizeof(uint32_t); in vdagent_send_clipboard_release()
384 } else if (info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { in vdagent_send_clipboard_release()
388 msg->type = VD_AGENT_CLIPBOARD_RELEASE; in vdagent_send_clipboard_release()
398 info->types[type].size); in vdagent_send_clipboard_data()
400 uint8_t *s = msg->data; in vdagent_send_clipboard_data()
401 uint32_t *data = (uint32_t *)msg->data; in vdagent_send_clipboard_data()
404 *s = info->selection; in vdagent_send_clipboard_data()
406 msg->size += sizeof(uint32_t); in vdagent_send_clipboard_data()
407 } else if (info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { in vdagent_send_clipboard_data()
413 msg->size += sizeof(uint32_t); in vdagent_send_clipboard_data()
415 memcpy(data, info->types[type].data, info->types[type].size); in vdagent_send_clipboard_data()
416 msg->size += info->types[type].size; in vdagent_send_clipboard_data()
418 msg->type = VD_AGENT_CLIPBOARD; in vdagent_send_clipboard_data()
426 g_autoptr(QemuClipboardInfo) info = qemu_clipboard_info_new(&vd->cbpeer, selection); in vdagent_send_empty_clipboard_data()
435 QemuClipboardSelection s = info->selection; in vdagent_clipboard_update_info()
437 bool self_update = info->owner == &vd->cbpeer; in vdagent_clipboard_update_info()
440 vd->cbpending[s] = 0; in vdagent_clipboard_update_info()
442 if (info->owner) { in vdagent_clipboard_update_info()
456 if (vd->cbpending[s] & (1 << type)) { in vdagent_clipboard_update_info()
457 vd->cbpending[s] &= ~(1 << type); in vdagent_clipboard_update_info()
478 switch (notify->type) { in vdagent_clipboard_notify()
480 vdagent_clipboard_update_info(vd, notify->info); in vdagent_clipboard_notify()
491 VDAgentChardev *vd = container_of(info->owner, VDAgentChardev, cbpeer); in vdagent_clipboard_request()
495 uint8_t *s = msg->data; in vdagent_clipboard_request()
496 uint32_t *data = (uint32_t *)msg->data; in vdagent_clipboard_request()
503 *s = info->selection; in vdagent_clipboard_request()
505 msg->size += sizeof(uint32_t); in vdagent_clipboard_request()
509 msg->size += sizeof(uint32_t); in vdagent_clipboard_request()
511 msg->type = VD_AGENT_CLIPBOARD_REQUEST; in vdagent_clipboard_request()
520 info = qemu_clipboard_info_new(&vd->cbpeer, s); in vdagent_clipboard_recv_grab()
522 if (vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { in vdagent_clipboard_recv_grab()
528 info->has_serial = true; in vdagent_clipboard_recv_grab()
529 info->serial = *(uint32_t *)data; in vdagent_clipboard_recv_grab()
530 if (info->serial < vd->last_serial[s]) { in vdagent_clipboard_recv_grab()
532 vd->last_serial[s], info->serial); in vdagent_clipboard_recv_grab()
533 /* discard lower-ordering guest grab */ in vdagent_clipboard_recv_grab()
536 vd->last_serial[s] = info->serial; in vdagent_clipboard_recv_grab()
538 size -= sizeof(uint32_t); in vdagent_clipboard_recv_grab()
552 info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true; in vdagent_clipboard_recv_grab()
558 size -= sizeof(uint32_t); in vdagent_clipboard_recv_grab()
580 if (info && info->types[type].available && info->owner != &vd->cbpeer) { in vdagent_clipboard_recv_request()
581 if (info->types[type].data) { in vdagent_clipboard_recv_request()
584 vd->cbpending[s] |= (1 << type); in vdagent_clipboard_recv_request()
607 size -= 4; in vdagent_clipboard_recv_data()
609 if (qemu_clipboard_peer_owns(&vd->cbpeer, s)) { in vdagent_clipboard_recv_data()
610 qemu_clipboard_set_data(&vd->cbpeer, qemu_clipboard_info(s), in vdagent_clipboard_recv_data()
617 qemu_clipboard_peer_release(&vd->cbpeer, s); in vdagent_clipboard_recv_release()
623 uint32_t size = msg->size; in vdagent_chr_recv_clipboard()
624 void *data = msg->data; in vdagent_chr_recv_clipboard()
635 size -= 4; in vdagent_chr_recv_clipboard()
638 switch (msg->type) { in vdagent_chr_recv_clipboard()
652 /* ------------------------------------------------------------------ */
661 ChardevQemuVDAgent *cfg = backend->u.qemu_vdagent.data; in vdagent_chr_open()
672 vd->mouse = VDAGENT_MOUSE_DEFAULT; in vdagent_chr_open()
673 if (cfg->has_mouse) { in vdagent_chr_open()
674 vd->mouse = cfg->mouse; in vdagent_chr_open()
677 vd->clipboard = VDAGENT_CLIPBOARD_DEFAULT; in vdagent_chr_open()
678 if (cfg->has_clipboard) { in vdagent_chr_open()
679 vd->clipboard = cfg->clipboard; in vdagent_chr_open()
682 if (vd->mouse) { in vdagent_chr_open()
683 vd->mouse_hs = qemu_input_handler_register(&vd->mouse_dev, in vdagent_chr_open()
692 if (vd->cbpeer.notifier.notify != NULL) { in vdagent_clipboard_peer_register()
696 vd->cbpeer.name = "vdagent"; in vdagent_clipboard_peer_register()
697 vd->cbpeer.notifier.notify = vdagent_clipboard_notify; in vdagent_clipboard_peer_register()
698 vd->cbpeer.request = vdagent_clipboard_request; in vdagent_clipboard_peer_register()
699 qemu_clipboard_peer_register(&vd->cbpeer); in vdagent_clipboard_peer_register()
704 VDAgentAnnounceCapabilities *caps = (void *)msg->data; in vdagent_chr_recv_caps()
707 if (msg->size < (sizeof(VDAgentAnnounceCapabilities) + in vdagent_chr_recv_caps()
713 if (caps->caps[0] & (1 << i)) { in vdagent_chr_recv_caps()
718 vd->caps = caps->caps[0]; in vdagent_chr_recv_caps()
719 if (caps->request) { in vdagent_chr_recv_caps()
722 if (have_mouse(vd) && vd->mouse_hs) { in vdagent_chr_recv_caps()
723 qemu_input_handler_activate(vd->mouse_hs); in vdagent_chr_recv_caps()
726 memset(vd->last_serial, 0, sizeof(vd->last_serial)); in vdagent_chr_recv_caps()
736 trace_vdagent_recv_msg(GET_NAME(msg_name, msg->type), msg->size); in vdagent_chr_recv_msg()
738 switch (msg->type) { in vdagent_chr_recv_msg()
757 g_clear_pointer(&vd->xbuf, g_free); in vdagent_reset_xbuf()
758 vd->xoff = 0; in vdagent_reset_xbuf()
759 vd->xsize = 0; in vdagent_reset_xbuf()
764 VDAgentMessage *msg = (void *)vd->msgbuf; in vdagent_chr_recv_chunk()
766 if (!vd->xsize) { in vdagent_chr_recv_chunk()
767 if (vd->msgsize < sizeof(*msg)) { in vdagent_chr_recv_chunk()
769 vd->msgsize, sizeof(*msg)); in vdagent_chr_recv_chunk()
772 if (vd->msgsize == msg->size + sizeof(*msg)) { in vdagent_chr_recv_chunk()
778 if (!vd->xsize) { in vdagent_chr_recv_chunk()
779 vd->xsize = msg->size + sizeof(*msg); in vdagent_chr_recv_chunk()
780 vd->xbuf = g_malloc0(vd->xsize); in vdagent_chr_recv_chunk()
783 if (vd->xoff + vd->msgsize > vd->xsize) { in vdagent_chr_recv_chunk()
785 vd->xoff, vd->msgsize, vd->xsize); in vdagent_chr_recv_chunk()
790 memcpy(vd->xbuf + vd->xoff, vd->msgbuf, vd->msgsize); in vdagent_chr_recv_chunk()
791 vd->xoff += vd->msgsize; in vdagent_chr_recv_chunk()
792 if (vd->xoff < vd->xsize) { in vdagent_chr_recv_chunk()
796 msg = (void *)vd->xbuf; in vdagent_chr_recv_chunk()
803 memset(&vd->chunk, 0, sizeof(vd->chunk)); in vdagent_reset_bufs()
804 vd->chunksize = 0; in vdagent_reset_bufs()
805 g_free(vd->msgbuf); in vdagent_reset_bufs()
806 vd->msgbuf = NULL; in vdagent_reset_bufs()
807 vd->msgsize = 0; in vdagent_reset_bufs()
816 if (vd->chunksize < sizeof(vd->chunk)) { in vdagent_chr_write()
817 copy = sizeof(vd->chunk) - vd->chunksize; in vdagent_chr_write()
821 memcpy((void *)(&vd->chunk) + vd->chunksize, buf, copy); in vdagent_chr_write()
822 vd->chunksize += copy; in vdagent_chr_write()
824 len -= copy; in vdagent_chr_write()
825 if (vd->chunksize < sizeof(vd->chunk)) { in vdagent_chr_write()
829 assert(vd->msgbuf == NULL); in vdagent_chr_write()
830 vd->msgbuf = g_malloc0(vd->chunk.size); in vdagent_chr_write()
833 copy = vd->chunk.size - vd->msgsize; in vdagent_chr_write()
837 memcpy(vd->msgbuf + vd->msgsize, buf, copy); in vdagent_chr_write()
838 vd->msgsize += copy; in vdagent_chr_write()
840 len -= copy; in vdagent_chr_write()
842 if (vd->msgsize == vd->chunk.size) { in vdagent_chr_write()
843 trace_vdagent_recv_chunk(vd->chunk.size); in vdagent_chr_write()
863 vd->connected = false; in vdagent_disconnect()
864 g_byte_array_set_size(vd->outbuf, 0); in vdagent_disconnect()
866 vd->caps = 0; in vdagent_disconnect()
867 if (vd->mouse_hs) { in vdagent_disconnect()
868 qemu_input_handler_deactivate(vd->mouse_hs); in vdagent_disconnect()
870 if (vd->cbpeer.notifier.notify) { in vdagent_disconnect()
871 qemu_clipboard_peer_unregister(&vd->cbpeer); in vdagent_disconnect()
872 memset(&vd->cbpeer, 0, sizeof(vd->cbpeer)); in vdagent_disconnect()
882 if (vd->connected == fe_open) { in vdagent_chr_set_fe_open()
895 vd->connected = true; in vdagent_chr_set_fe_open()
904 backend->type = CHARDEV_BACKEND_KIND_QEMU_VDAGENT; in vdagent_chr_parse()
905 cfg = backend->u.qemu_vdagent.data = g_new0(ChardevQemuVDAgent, 1); in vdagent_chr_parse()
907 cfg->has_mouse = true; in vdagent_chr_parse()
908 cfg->mouse = qemu_opt_get_bool(opts, "mouse", VDAGENT_MOUSE_DEFAULT); in vdagent_chr_parse()
909 cfg->has_clipboard = true; in vdagent_chr_parse()
910 cfg->clipboard = qemu_opt_get_bool(opts, "clipboard", VDAGENT_CLIPBOARD_DEFAULT); in vdagent_chr_parse()
913 /* ------------------------------------------------------------------ */
919 cc->parse = vdagent_chr_parse; in vdagent_chr_class_init()
920 cc->open = vdagent_chr_open; in vdagent_chr_class_init()
921 cc->chr_write = vdagent_chr_write; in vdagent_chr_class_init()
922 cc->chr_set_fe_open = vdagent_chr_set_fe_open; in vdagent_chr_class_init()
923 cc->chr_accept_input = vdagent_chr_accept_input; in vdagent_chr_class_init()
930 if (have_mouse(vd) && vd->mouse_hs) { in post_load()
931 qemu_input_handler_activate(vd->mouse_hs); in post_load()
990 if (qemu_clipboard_peer_owns(&vd->cbpeer, i)) { in put_cbinfo()
1018 qemu_clipboard_info_new(&vd->cbpeer, cbinfo.cbinfo[i].selection); in get_cbinfo()
1020 memcpy(info->types, cbinfo.cbinfo[i].types, sizeof(cbinfo.cbinfo[i].types)); in get_cbinfo()
1070 vd->outbuf = g_byte_array_new(); in vdagent_chr_init()
1079 if (vd->mouse_hs) { in vdagent_chr_fini()
1080 qemu_input_handler_unregister(vd->mouse_hs); in vdagent_chr_fini()
1082 g_clear_pointer(&vd->outbuf, g_byte_array_unref); in vdagent_chr_fini()