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