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