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