linux/drivers/staging/vboxvideo/hgsmi_base.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2006-2017 Oracle Corporation
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 */
  22
  23#include "vbox_drv.h"
  24#include "vbox_err.h"
  25#include "vboxvideo_guest.h"
  26#include "vboxvideo_vbe.h"
  27#include "hgsmi_channels.h"
  28#include "hgsmi_ch_setup.h"
  29
  30/**
  31 * Inform the host of the location of the host flags in VRAM via an HGSMI cmd.
  32 * @param    ctx          the context of the guest heap to use.
  33 * @param    location     the offset chosen for the flags within guest VRAM.
  34 * @returns 0 on success, -errno on failure
  35 */
  36int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location)
  37{
  38        struct hgsmi_buffer_location *p;
  39
  40        p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI,
  41                               HGSMI_CC_HOST_FLAGS_LOCATION);
  42        if (!p)
  43                return -ENOMEM;
  44
  45        p->buf_location = location;
  46        p->buf_len = sizeof(struct hgsmi_host_flags);
  47
  48        hgsmi_buffer_submit(ctx, p);
  49        hgsmi_buffer_free(ctx, p);
  50
  51        return 0;
  52}
  53
  54/**
  55 * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
  56 * @param    ctx                 the context of the guest heap to use.
  57 * @param    caps                the capabilities to report, see vbva_caps.
  58 * @returns 0 on success, -errno on failure
  59 */
  60int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps)
  61{
  62        struct vbva_caps *p;
  63
  64        p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
  65        if (!p)
  66                return -ENOMEM;
  67
  68        p->rc = VERR_NOT_IMPLEMENTED;
  69        p->caps = caps;
  70
  71        hgsmi_buffer_submit(ctx, p);
  72
  73        WARN_ON_ONCE(RT_FAILURE(p->rc));
  74
  75        hgsmi_buffer_free(ctx, p);
  76
  77        return 0;
  78}
  79
  80int hgsmi_test_query_conf(struct gen_pool *ctx)
  81{
  82        u32 value = 0;
  83        int ret;
  84
  85        ret = hgsmi_query_conf(ctx, U32_MAX, &value);
  86        if (ret)
  87                return ret;
  88
  89        return value == U32_MAX ? 0 : -EIO;
  90}
  91
  92/**
  93 * Query the host for an HGSMI configuration parameter via an HGSMI command.
  94 * @param  ctx        the context containing the heap used
  95 * @param  index      the index of the parameter to query,
  96 *                    @see vbva_conf32::index
  97 * @param  value_ret  where to store the value of the parameter on success
  98 * @returns 0 on success, -errno on failure
  99 */
 100int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret)
 101{
 102        struct vbva_conf32 *p;
 103
 104        p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
 105                               VBVA_QUERY_CONF32);
 106        if (!p)
 107                return -ENOMEM;
 108
 109        p->index = index;
 110        p->value = U32_MAX;
 111
 112        hgsmi_buffer_submit(ctx, p);
 113
 114        *value_ret = p->value;
 115
 116        hgsmi_buffer_free(ctx, p);
 117
 118        return 0;
 119}
 120
 121/**
 122 * Pass the host a new mouse pointer shape via an HGSMI command.
 123 *
 124 * @param  ctx      the context containing the heap to be used
 125 * @param  flags    cursor flags, @see VMMDevReqMousePointer::flags
 126 * @param  hot_x    horizontal position of the hot spot
 127 * @param  hot_y    vertical position of the hot spot
 128 * @param  width    width in pixels of the cursor
 129 * @param  height   height in pixels of the cursor
 130 * @param  pixels   pixel data, @see VMMDevReqMousePointer for the format
 131 * @param  len      size in bytes of the pixel data
 132 * @returns 0 on success, -errno on failure
 133 */
 134int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
 135                               u32 hot_x, u32 hot_y, u32 width, u32 height,
 136                               u8 *pixels, u32 len)
 137{
 138        struct vbva_mouse_pointer_shape *p;
 139        u32 pixel_len = 0;
 140        int rc;
 141
 142        if (flags & VBOX_MOUSE_POINTER_SHAPE) {
 143                /*
 144                 * Size of the pointer data:
 145                 * sizeof (AND mask) + sizeof (XOR_MASK)
 146                 */
 147                pixel_len = ((((width + 7) / 8) * height + 3) & ~3) +
 148                         width * 4 * height;
 149                if (pixel_len > len)
 150                        return -EINVAL;
 151
 152                /*
 153                 * If shape is supplied, then always create the pointer visible.
 154                 * See comments in 'vboxUpdatePointerShape'
 155                 */
 156                flags |= VBOX_MOUSE_POINTER_VISIBLE;
 157        }
 158
 159        p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
 160                               VBVA_MOUSE_POINTER_SHAPE);
 161        if (!p)
 162                return -ENOMEM;
 163
 164        p->result = VINF_SUCCESS;
 165        p->flags = flags;
 166        p->hot_X = hot_x;
 167        p->hot_y = hot_y;
 168        p->width = width;
 169        p->height = height;
 170        if (pixel_len)
 171                memcpy(p->data, pixels, pixel_len);
 172
 173        hgsmi_buffer_submit(ctx, p);
 174
 175        switch (p->result) {
 176        case VINF_SUCCESS:
 177                rc = 0;
 178                break;
 179        case VERR_NO_MEMORY:
 180                rc = -ENOMEM;
 181                break;
 182        case VERR_NOT_SUPPORTED:
 183                rc = -EBUSY;
 184                break;
 185        default:
 186                rc = -EINVAL;
 187        }
 188
 189        hgsmi_buffer_free(ctx, p);
 190
 191        return rc;
 192}
 193
 194/**
 195 * Report the guest cursor position.  The host may wish to use this information
 196 * to re-position its own cursor (though this is currently unlikely).  The
 197 * current host cursor position is returned.
 198 * @param  ctx              The context containing the heap used.
 199 * @param  report_position  Are we reporting a position?
 200 * @param  x                Guest cursor X position.
 201 * @param  y                Guest cursor Y position.
 202 * @param  x_host           Host cursor X position is stored here.  Optional.
 203 * @param  y_host           Host cursor Y position is stored here.  Optional.
 204 * @returns 0 on success, -errno on failure
 205 */
 206int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position,
 207                          u32 x, u32 y, u32 *x_host, u32 *y_host)
 208{
 209        struct vbva_cursor_position *p;
 210
 211        p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
 212                               VBVA_CURSOR_POSITION);
 213        if (!p)
 214                return -ENOMEM;
 215
 216        p->report_position = report_position;
 217        p->x = x;
 218        p->y = y;
 219
 220        hgsmi_buffer_submit(ctx, p);
 221
 222        *x_host = p->x;
 223        *y_host = p->y;
 224
 225        hgsmi_buffer_free(ctx, p);
 226
 227        return 0;
 228}
 229
 230/**
 231 * @todo Mouse pointer position to be read from VMMDev memory, address of the
 232 * memory region can be queried from VMMDev via an IOCTL. This VMMDev memory
 233 * region will contain host information which is needed by the guest.
 234 *
 235 * Reading will not cause a switch to the host.
 236 *
 237 * Have to take into account:
 238 *  * synchronization: host must write to the memory only from EMT,
 239 *    large structures must be read under flag, which tells the host
 240 *    that the guest is currently reading the memory (OWNER flag?).
 241 *  * guest writes: may be allocate a page for the host info and make
 242 *    the page readonly for the guest.
 243 *  * the information should be available only for additions drivers.
 244 *  * VMMDev additions driver will inform the host which version of the info
 245 *    it expects, host must support all versions.
 246 */
 247