1 // SPDX-License-Identifier: MIT 2 /* Copyright (C) 2006-2017 Oracle Corporation */ 3 4 #include <linux/vbox_err.h> 5 #include "vbox_drv.h" 6 #include "vboxvideo_guest.h" 7 #include "vboxvideo_vbe.h" 8 #include "hgsmi_channels.h" 9 #include "hgsmi_ch_setup.h" 10 11 /** 12 * Inform the host of the location of the host flags in VRAM via an HGSMI cmd. 13 * Return: 0 or negative errno value. 14 * @ctx: The context of the guest heap to use. 15 * @location: The offset chosen for the flags within guest VRAM. 16 */ 17 int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location) 18 { 19 struct hgsmi_buffer_location *p; 20 21 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI, 22 HGSMI_CC_HOST_FLAGS_LOCATION); 23 if (!p) 24 return -ENOMEM; 25 26 p->buf_location = location; 27 p->buf_len = sizeof(struct hgsmi_host_flags); 28 29 hgsmi_buffer_submit(ctx, p); 30 hgsmi_buffer_free(ctx, p); 31 32 return 0; 33 } 34 35 /** 36 * Notify the host of HGSMI-related guest capabilities via an HGSMI command. 37 * Return: 0 or negative errno value. 38 * @ctx: The context of the guest heap to use. 39 * @caps: The capabilities to report, see vbva_caps. 40 */ 41 int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps) 42 { 43 struct vbva_caps *p; 44 45 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS); 46 if (!p) 47 return -ENOMEM; 48 49 p->rc = VERR_NOT_IMPLEMENTED; 50 p->caps = caps; 51 52 hgsmi_buffer_submit(ctx, p); 53 54 WARN_ON_ONCE(p->rc < 0); 55 56 hgsmi_buffer_free(ctx, p); 57 58 return 0; 59 } 60 61 int hgsmi_test_query_conf(struct gen_pool *ctx) 62 { 63 u32 value = 0; 64 int ret; 65 66 ret = hgsmi_query_conf(ctx, U32_MAX, &value); 67 if (ret) 68 return ret; 69 70 return value == U32_MAX ? 0 : -EIO; 71 } 72 73 /** 74 * Query the host for an HGSMI configuration parameter via an HGSMI command. 75 * Return: 0 or negative errno value. 76 * @ctx: The context containing the heap used. 77 * @index: The index of the parameter to query. 78 * @value_ret: Where to store the value of the parameter on success. 79 */ 80 int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret) 81 { 82 struct vbva_conf32 *p; 83 84 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, 85 VBVA_QUERY_CONF32); 86 if (!p) 87 return -ENOMEM; 88 89 p->index = index; 90 p->value = U32_MAX; 91 92 hgsmi_buffer_submit(ctx, p); 93 94 *value_ret = p->value; 95 96 hgsmi_buffer_free(ctx, p); 97 98 return 0; 99 } 100 101 /** 102 * Pass the host a new mouse pointer shape via an HGSMI command. 103 * Return: 0 or negative errno value. 104 * @ctx: The context containing the heap to be used. 105 * @flags: Cursor flags. 106 * @hot_x: Horizontal position of the hot spot. 107 * @hot_y: Vertical position of the hot spot. 108 * @width: Width in pixels of the cursor. 109 * @height: Height in pixels of the cursor. 110 * @pixels: Pixel data, @see VMMDevReqMousePointer for the format. 111 * @len: Size in bytes of the pixel data. 112 */ 113 int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags, 114 u32 hot_x, u32 hot_y, u32 width, u32 height, 115 u8 *pixels, u32 len) 116 { 117 struct vbva_mouse_pointer_shape *p; 118 u32 pixel_len = 0; 119 int rc; 120 121 if (flags & VBOX_MOUSE_POINTER_SHAPE) { 122 /* 123 * Size of the pointer data: 124 * sizeof (AND mask) + sizeof (XOR_MASK) 125 */ 126 pixel_len = ((((width + 7) / 8) * height + 3) & ~3) + 127 width * 4 * height; 128 if (pixel_len > len) 129 return -EINVAL; 130 131 /* 132 * If shape is supplied, then always create the pointer visible. 133 * See comments in 'vboxUpdatePointerShape' 134 */ 135 flags |= VBOX_MOUSE_POINTER_VISIBLE; 136 } 137 138 p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA, 139 VBVA_MOUSE_POINTER_SHAPE); 140 if (!p) 141 return -ENOMEM; 142 143 p->result = VINF_SUCCESS; 144 p->flags = flags; 145 p->hot_X = hot_x; 146 p->hot_y = hot_y; 147 p->width = width; 148 p->height = height; 149 if (pixel_len) 150 memcpy(p->data, pixels, pixel_len); 151 152 hgsmi_buffer_submit(ctx, p); 153 154 switch (p->result) { 155 case VINF_SUCCESS: 156 rc = 0; 157 break; 158 case VERR_NO_MEMORY: 159 rc = -ENOMEM; 160 break; 161 case VERR_NOT_SUPPORTED: 162 rc = -EBUSY; 163 break; 164 default: 165 rc = -EINVAL; 166 } 167 168 hgsmi_buffer_free(ctx, p); 169 170 return rc; 171 } 172 173 /** 174 * Report the guest cursor position. The host may wish to use this information 175 * to re-position its own cursor (though this is currently unlikely). The 176 * current host cursor position is returned. 177 * Return: 0 or negative errno value. 178 * @ctx: The context containing the heap used. 179 * @report_position: Are we reporting a position? 180 * @x: Guest cursor X position. 181 * @y: Guest cursor Y position. 182 * @x_host: Host cursor X position is stored here. Optional. 183 * @y_host: Host cursor Y position is stored here. Optional. 184 */ 185 int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position, 186 u32 x, u32 y, u32 *x_host, u32 *y_host) 187 { 188 struct vbva_cursor_position *p; 189 190 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, 191 VBVA_CURSOR_POSITION); 192 if (!p) 193 return -ENOMEM; 194 195 p->report_position = report_position; 196 p->x = x; 197 p->y = y; 198 199 hgsmi_buffer_submit(ctx, p); 200 201 *x_host = p->x; 202 *y_host = p->y; 203 204 hgsmi_buffer_free(ctx, p); 205 206 return 0; 207 } 208