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 */
hgsmi_report_flags_location(struct gen_pool * ctx,u32 location)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 */
hgsmi_send_caps_info(struct gen_pool * ctx,u32 caps)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
hgsmi_test_query_conf(struct gen_pool * ctx)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 */
hgsmi_query_conf(struct gen_pool * ctx,u32 index,u32 * value_ret)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 */
hgsmi_update_pointer_shape(struct gen_pool * ctx,u32 flags,u32 hot_x,u32 hot_y,u32 width,u32 height,u8 * pixels,u32 len)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 */
hgsmi_cursor_position(struct gen_pool * ctx,bool report_position,u32 x,u32 y,u32 * x_host,u32 * y_host)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