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