// SPDX-License-Identifier: MIT /* Copyright (C) 2006-2017 Oracle Corporation */ #include #include "vbox_drv.h" #include "vboxvideo_guest.h" #include "vboxvideo_vbe.h" #include "hgsmi_channels.h" #include "hgsmi_ch_setup.h" /** * hgsmi_report_flags_location - Inform the host of the location of * the host flags in VRAM via an HGSMI cmd. * Return: 0 or negative errno value. * @ctx: The context of the guest heap to use. * @location: The offset chosen for the flags within guest VRAM. */ int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location) { struct hgsmi_buffer_location *p; p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI, HGSMI_CC_HOST_FLAGS_LOCATION); if (!p) return -ENOMEM; p->buf_location = location; p->buf_len = sizeof(struct hgsmi_host_flags); hgsmi_buffer_submit(ctx, p); hgsmi_buffer_free(ctx, p); return 0; } /** * hgsmi_send_caps_info - Notify the host of HGSMI-related guest capabilities * via an HGSMI command. * Return: 0 or negative errno value. * @ctx: The context of the guest heap to use. * @caps: The capabilities to report, see vbva_caps. */ int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps) { struct vbva_caps *p; p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS); if (!p) return -ENOMEM; p->rc = VERR_NOT_IMPLEMENTED; p->caps = caps; hgsmi_buffer_submit(ctx, p); WARN_ON_ONCE(p->rc < 0); hgsmi_buffer_free(ctx, p); return 0; } int hgsmi_test_query_conf(struct gen_pool *ctx) { u32 value = 0; int ret; ret = hgsmi_query_conf(ctx, U32_MAX, &value); if (ret) return ret; return value == U32_MAX ? 0 : -EIO; } /** * hgsmi_query_conf - Query the host for an HGSMI configuration * parameter via an HGSMI command. * Return: 0 or negative errno value. * @ctx: The context containing the heap used. * @index: The index of the parameter to query. * @value_ret: Where to store the value of the parameter on success. */ int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret) { struct vbva_conf32 *p; p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_QUERY_CONF32); if (!p) return -ENOMEM; p->index = index; p->value = U32_MAX; hgsmi_buffer_submit(ctx, p); *value_ret = p->value; hgsmi_buffer_free(ctx, p); return 0; } /** * hgsmi_update_pointer_shape - Pass the host a new mouse pointer shape * via an HGSMI command. * Return: 0 or negative errno value. * @ctx: The context containing the heap to be used. * @flags: Cursor flags. * @hot_x: Horizontal position of the hot spot. * @hot_y: Vertical position of the hot spot. * @width: Width in pixels of the cursor. * @height: Height in pixels of the cursor. * @pixels: Pixel data, @see VMMDevReqMousePointer for the format. * @len: Size in bytes of the pixel data. */ int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags, u32 hot_x, u32 hot_y, u32 width, u32 height, u8 *pixels, u32 len) { struct vbva_mouse_pointer_shape *p; u32 pixel_len = 0; int rc; if (flags & VBOX_MOUSE_POINTER_SHAPE) { /* * Size of the pointer data: * sizeof (AND mask) + sizeof (XOR_MASK) */ pixel_len = ((((width + 7) / 8) * height + 3) & ~3) + width * 4 * height; if (pixel_len > len) return -EINVAL; /* * If shape is supplied, then always create the pointer visible. * See comments in 'vboxUpdatePointerShape' */ flags |= VBOX_MOUSE_POINTER_VISIBLE; } p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA, VBVA_MOUSE_POINTER_SHAPE); if (!p) return -ENOMEM; p->result = VINF_SUCCESS; p->flags = flags; p->hot_X = hot_x; p->hot_y = hot_y; p->width = width; p->height = height; if (pixel_len) memcpy(p->data, pixels, pixel_len); hgsmi_buffer_submit(ctx, p); switch (p->result) { case VINF_SUCCESS: rc = 0; break; case VERR_NO_MEMORY: rc = -ENOMEM; break; case VERR_NOT_SUPPORTED: rc = -EBUSY; break; default: rc = -EINVAL; } hgsmi_buffer_free(ctx, p); return rc; } /** * hgsmi_cursor_position - Report the guest cursor position. The host may * wish to use this information to re-position its * own cursor (though this is currently unlikely). * The current host cursor position is returned. * Return: 0 or negative errno value. * @ctx: The context containing the heap used. * @report_position: Are we reporting a position? * @x: Guest cursor X position. * @y: Guest cursor Y position. * @x_host: Host cursor X position is stored here. Optional. * @y_host: Host cursor Y position is stored here. Optional. */ int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position, u32 x, u32 y, u32 *x_host, u32 *y_host) { struct vbva_cursor_position *p; p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_CURSOR_POSITION); if (!p) return -ENOMEM; p->report_position = report_position; p->x = x; p->y = y; hgsmi_buffer_submit(ctx, p); *x_host = p->x; *y_host = p->y; hgsmi_buffer_free(ctx, p); return 0; }