213 lines
5.2 KiB
C
213 lines
5.2 KiB
C
|
// SPDX-License-Identifier: MIT
|
||
|
/* Copyright (C) 2006-2017 Oracle Corporation */
|
||
|
|
||
|
#include <linux/vbox_err.h>
|
||
|
#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;
|
||
|
}
|