VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp@ 68654

Last change on this file since 68654 was 67145, checked in by vboxsync, 8 years ago

bugref:8524: Additions/linux: play nicely with distribution-installed Additions
Rename HGSMIBufferAlloc.cpp to HGSMIBuffers.cpp and move VBoxHGSMIBufferSubmit() there.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.7 KB
Line 
1/* $Id: HGSMIBase.cpp 67145 2017-05-30 15:11:29Z vboxsync $ */
2/** @file
3 * VirtualBox Video driver, common code - HGSMI guest-to-host communication.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28#include <VBoxVideoGuest.h>
29#include <VBoxVideoVBE.h>
30#include <VBoxVideoIPRT.h>
31
32/** Detect whether HGSMI is supported by the host. */
33DECLHIDDEN(bool) VBoxHGSMIIsSupported(void)
34{
35 uint16_t DispiId;
36
37 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
38 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_HGSMI);
39
40 DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
41
42 return (DispiId == VBE_DISPI_ID_HGSMI);
43}
44
45
46/**
47 * Inform the host of the location of the host flags in VRAM via an HGSMI
48 * command.
49 * @returns IPRT status value.
50 * @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
51 * @returns VERR_NO_MEMORY if a heap allocation fails.
52 * @param pCtx the context of the guest heap to use.
53 * @param offLocation the offset chosen for the flags withing guest
54 * VRAM.
55 */
56DECLHIDDEN(int) VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
57 HGSMIOFFSET offLocation)
58{
59 HGSMIBUFFERLOCATION *p;
60 int rc = VINF_SUCCESS;
61
62 /* Allocate the IO buffer. */
63 p = (HGSMIBUFFERLOCATION *)VBoxHGSMIBufferAlloc(pCtx,
64 sizeof(HGSMIBUFFERLOCATION),
65 HGSMI_CH_HGSMI,
66 HGSMI_CC_HOST_FLAGS_LOCATION);
67 if (p)
68 {
69 /* Prepare data to be sent to the host. */
70 p->offLocation = offLocation;
71 p->cbLocation = sizeof(HGSMIHOSTFLAGS);
72 rc = VBoxHGSMIBufferSubmit(pCtx, p);
73 /* Free the IO buffer. */
74 VBoxHGSMIBufferFree(pCtx, p);
75 }
76 else
77 rc = VERR_NO_MEMORY;
78 return rc;
79}
80
81
82/**
83 * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
84 * @returns IPRT status value.
85 * @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
86 * @returns VERR_NO_MEMORY if a heap allocation fails.
87 * @param pCtx the context of the guest heap to use.
88 * @param fCaps the capabilities to report, see VBVACAPS.
89 */
90DECLHIDDEN(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
91 uint32_t fCaps)
92{
93 VBVACAPS *pCaps;
94 int rc = VINF_SUCCESS;
95
96 /* Allocate the IO buffer. */
97 pCaps = (VBVACAPS *)VBoxHGSMIBufferAlloc(pCtx,
98 sizeof(VBVACAPS), HGSMI_CH_VBVA,
99 VBVA_INFO_CAPS);
100
101 if (pCaps)
102 {
103 /* Prepare data to be sent to the host. */
104 pCaps->rc = VERR_NOT_IMPLEMENTED;
105 pCaps->fCaps = fCaps;
106 rc = VBoxHGSMIBufferSubmit(pCtx, pCaps);
107 if (RT_SUCCESS(rc))
108 {
109 AssertRC(pCaps->rc);
110 rc = pCaps->rc;
111 }
112 /* Free the IO buffer. */
113 VBoxHGSMIBufferFree(pCtx, pCaps);
114 }
115 else
116 rc = VERR_NO_MEMORY;
117 return rc;
118}
119
120
121/**
122 * Get the information needed to map the basic communication structures in
123 * device memory into our address space. All pointer parameters are optional.
124 *
125 * @param cbVRAM how much video RAM is allocated to the device
126 * @param poffVRAMBaseMapping where to save the offset from the start of the
127 * device VRAM of the whole area to map
128 * @param pcbMapping where to save the mapping size
129 * @param poffGuestHeapMemory where to save the offset into the mapped area
130 * of the guest heap backing memory
131 * @param pcbGuestHeapMemory where to save the size of the guest heap
132 * backing memory
133 * @param poffHostFlags where to save the offset into the mapped area
134 * of the host flags
135 */
136DECLHIDDEN(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
137 uint32_t *poffVRAMBaseMapping,
138 uint32_t *pcbMapping,
139 uint32_t *poffGuestHeapMemory,
140 uint32_t *pcbGuestHeapMemory,
141 uint32_t *poffHostFlags)
142{
143 AssertPtrNullReturnVoid(poffVRAMBaseMapping);
144 AssertPtrNullReturnVoid(pcbMapping);
145 AssertPtrNullReturnVoid(poffGuestHeapMemory);
146 AssertPtrNullReturnVoid(pcbGuestHeapMemory);
147 AssertPtrNullReturnVoid(poffHostFlags);
148 if (poffVRAMBaseMapping)
149 *poffVRAMBaseMapping = cbVRAM - VBVA_ADAPTER_INFORMATION_SIZE;
150 if (pcbMapping)
151 *pcbMapping = VBVA_ADAPTER_INFORMATION_SIZE;
152 if (poffGuestHeapMemory)
153 *poffGuestHeapMemory = 0;
154 if (pcbGuestHeapMemory)
155 *pcbGuestHeapMemory = VBVA_ADAPTER_INFORMATION_SIZE
156 - sizeof(HGSMIHOSTFLAGS);
157 if (poffHostFlags)
158 *poffHostFlags = VBVA_ADAPTER_INFORMATION_SIZE
159 - sizeof(HGSMIHOSTFLAGS);
160}
161
162
163/** Sanity test on first call. We do not worry about concurrency issues. */
164static int testQueryConf(PHGSMIGUESTCOMMANDCONTEXT pCtx)
165{
166 static bool cOnce = false;
167 uint32_t ulValue = 0;
168 int rc;
169
170 if (cOnce)
171 return VINF_SUCCESS;
172 cOnce = true;
173 rc = VBoxQueryConfHGSMI(pCtx, UINT32_MAX, &ulValue);
174 if (RT_SUCCESS(rc) && ulValue == UINT32_MAX)
175 return VINF_SUCCESS;
176 cOnce = false;
177 if (RT_FAILURE(rc))
178 return rc;
179 return VERR_INTERNAL_ERROR;
180}
181
182
183/**
184 * Query the host for an HGSMI configuration parameter via an HGSMI command.
185 * @returns iprt status value
186 * @param pCtx the context containing the heap used
187 * @param u32Index the index of the parameter to query,
188 * @see VBVACONF32::u32Index
189 * @param u32DefValue defaut value
190 * @param pulValue where to store the value of the parameter on success
191 */
192DECLHIDDEN(int) VBoxQueryConfHGSMIDef(PHGSMIGUESTCOMMANDCONTEXT pCtx,
193 uint32_t u32Index, uint32_t u32DefValue, uint32_t *pulValue)
194{
195 int rc = VINF_SUCCESS;
196 VBVACONF32 *p;
197 // LogFunc(("u32Index = %d\n", u32Index));
198
199 rc = testQueryConf(pCtx);
200 if (RT_FAILURE(rc))
201 return rc;
202 /* Allocate the IO buffer. */
203 p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx,
204 sizeof(VBVACONF32), HGSMI_CH_VBVA,
205 VBVA_QUERY_CONF32);
206 if (p)
207 {
208 /* Prepare data to be sent to the host. */
209 p->u32Index = u32Index;
210 p->u32Value = u32DefValue;
211 rc = VBoxHGSMIBufferSubmit(pCtx, p);
212 if (RT_SUCCESS(rc))
213 {
214 *pulValue = p->u32Value;
215 // LogFunc(("u32Value = %d\n", p->u32Value));
216 }
217 /* Free the IO buffer. */
218 VBoxHGSMIBufferFree(pCtx, p);
219 }
220 else
221 rc = VERR_NO_MEMORY;
222 // LogFunc(("rc = %d\n", rc));
223 return rc;
224}
225
226DECLHIDDEN(int) VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx,
227 uint32_t u32Index, uint32_t *pulValue)
228{
229 return VBoxQueryConfHGSMIDef(pCtx, u32Index, UINT32_MAX, pulValue);
230}
231
232/**
233 * Pass the host a new mouse pointer shape via an HGSMI command.
234 *
235 * @returns success or failure
236 * @param pCtx the context containing the heap to be used
237 * @param fFlags cursor flags, @see VMMDevReqMousePointer::fFlags
238 * @param cHotX horizontal position of the hot spot
239 * @param cHotY vertical position of the hot spot
240 * @param cWidth width in pixels of the cursor
241 * @param cHeight height in pixels of the cursor
242 * @param pPixels pixel data, @see VMMDevReqMousePointer for the format
243 * @param cbLength size in bytes of the pixel data
244 */
245DECLHIDDEN(int) VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx,
246 uint32_t fFlags,
247 uint32_t cHotX,
248 uint32_t cHotY,
249 uint32_t cWidth,
250 uint32_t cHeight,
251 uint8_t *pPixels,
252 uint32_t cbLength)
253{
254 VBVAMOUSEPOINTERSHAPE *p;
255 uint32_t cbData = 0;
256 int rc = VINF_SUCCESS;
257
258 if (fFlags & VBOX_MOUSE_POINTER_SHAPE)
259 {
260 /* Size of the pointer data: sizeof (AND mask) + sizeof (XOR_MASK) */
261 cbData = ((((cWidth + 7) / 8) * cHeight + 3) & ~3)
262 + cWidth * 4 * cHeight;
263 /* If shape is supplied, then always create the pointer visible.
264 * See comments in 'vboxUpdatePointerShape'
265 */
266 fFlags |= VBOX_MOUSE_POINTER_VISIBLE;
267 }
268 // LogFlowFunc(("cbData %d, %dx%d\n", cbData, cWidth, cHeight));
269 if (cbData > cbLength)
270 {
271 // LogFunc(("calculated pointer data size is too big (%d bytes, limit %d)\n",
272 // cbData, cbLength));
273 return VERR_INVALID_PARAMETER;
274 }
275 /* Allocate the IO buffer. */
276 p = (VBVAMOUSEPOINTERSHAPE *)VBoxHGSMIBufferAlloc(pCtx,
277 sizeof(VBVAMOUSEPOINTERSHAPE)
278 + cbData,
279 HGSMI_CH_VBVA,
280 VBVA_MOUSE_POINTER_SHAPE);
281 if (p)
282 {
283 /* Prepare data to be sent to the host. */
284 /* Will be updated by the host. */
285 p->i32Result = VINF_SUCCESS;
286 /* We have our custom flags in the field */
287 p->fu32Flags = fFlags;
288 p->u32HotX = cHotX;
289 p->u32HotY = cHotY;
290 p->u32Width = cWidth;
291 p->u32Height = cHeight;
292 if (p->fu32Flags & VBOX_MOUSE_POINTER_SHAPE)
293 /* Copy the actual pointer data. */
294 memcpy (p->au8Data, pPixels, cbData);
295 rc = VBoxHGSMIBufferSubmit(pCtx, p);
296 if (RT_SUCCESS(rc))
297 rc = p->i32Result;
298 /* Free the IO buffer. */
299 VBoxHGSMIBufferFree(pCtx, p);
300 }
301 else
302 rc = VERR_NO_MEMORY;
303 // LogFlowFunc(("rc %d\n", rc));
304 return rc;
305}
306
307
308/**
309 * Report the guest cursor position. The host may wish to use this information
310 * to re-position its own cursor (though this is currently unlikely). The
311 * current host cursor position is returned.
312 * @param pCtx The context containing the heap used.
313 * @param fReportPosition Are we reporting a position?
314 * @param x Guest cursor X position.
315 * @param y Guest cursor Y position.
316 * @param pxHost Host cursor X position is stored here. Optional.
317 * @param pyHost Host cursor Y position is stored here. Optional.
318 * @returns iprt status code.
319 * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
320 */
321DECLHIDDEN(int) VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y,
322 uint32_t *pxHost, uint32_t *pyHost)
323{
324 int rc = VINF_SUCCESS;
325 VBVACURSORPOSITION *p;
326 // Log(("%s: x=%u, y=%u\n", __PRETTY_FUNCTION__, (unsigned)x, (unsigned)y));
327
328 /* Allocate the IO buffer. */
329 p = (VBVACURSORPOSITION *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVACURSORPOSITION), HGSMI_CH_VBVA, VBVA_CURSOR_POSITION);
330 if (p)
331 {
332 /* Prepare data to be sent to the host. */
333 p->fReportPosition = fReportPosition ? 1 : 0;
334 p->x = x;
335 p->y = y;
336 rc = VBoxHGSMIBufferSubmit(pCtx, p);
337 if (RT_SUCCESS(rc))
338 {
339 if (pxHost)
340 *pxHost = p->x;
341 if (pyHost)
342 *pyHost = p->y;
343 // Log(("%s: return: x=%u, y=%u\n", __PRETTY_FUNCTION__, (unsigned)p->x, (unsigned)p->y));
344 }
345 /* Free the IO buffer. */
346 VBoxHGSMIBufferFree(pCtx, p);
347 }
348 else
349 rc = VERR_NO_MEMORY;
350 // LogFunc(("rc = %d\n", rc));
351 return rc;
352}
353
354
355/** @todo Mouse pointer position to be read from VMMDev memory, address of the memory region
356 * can be queried from VMMDev via an IOCTL. This VMMDev memory region will contain
357 * host information which is needed by the guest.
358 *
359 * Reading will not cause a switch to the host.
360 *
361 * Have to take into account:
362 * * synchronization: host must write to the memory only from EMT,
363 * large structures must be read under flag, which tells the host
364 * that the guest is currently reading the memory (OWNER flag?).
365 * * guest writes: may be allocate a page for the host info and make
366 * the page readonly for the guest.
367 * * the information should be available only for additions drivers.
368 * * VMMDev additions driver will inform the host which version of the info it expects,
369 * host must support all versions.
370 *
371 */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette