VirtualBox

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

最後變更 在這個檔案從66544是 66544,由 vboxsync 提交於 8 年 前

bugref:8524: Additions/linux: play nicely with distribution-installed Additions
Change header of files which are expected to end up in the Linux kernel to the MIT licence to simplify life for people wanting to port vboxvideo to other kernels and to simplify synchronising changes back to VirtualBox. Update author information in files which have it, but do not add it to files which do not.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 25.5 KB
 
1/* $Id: HGSMIBase.cpp 66544 2017-04-12 17:02:30Z vboxsync $ */
2/** @file
3 * VirtualBox Video driver, common code - HGSMI initialisation and helper
4 * functions.
5 */
6
7/*
8 * Copyright (C) 2006-2017 Oracle Corporation
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 * OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29#include <VBoxVideoGuest.h>
30#include <VBoxVideoVBE.h>
31#include <VBoxVideoIPRT.h>
32
33/** Send completion notification to the host for the command located at offset
34 * @a offt into the host command buffer. */
35static void HGSMINotifyHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, HGSMIOFFSET offt)
36{
37 VBVO_PORT_WRITE_U32(pCtx->port, offt);
38}
39
40
41/**
42 * Inform the host that a command has been handled.
43 *
44 * @param pCtx the context containing the heap to be used
45 * @param pvMem pointer into the heap as mapped in @a pCtx to the command to
46 * be completed
47 */
48DECLHIDDEN(void) VBoxHGSMIHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx,
49 void *pvMem)
50{
51 HGSMIBUFFERHEADER *pHdr = HGSMIBufferHeaderFromData(pvMem);
52 HGSMIOFFSET offMem = HGSMIPointerToOffset(&pCtx->areaCtx, pHdr);
53 Assert(offMem != HGSMIOFFSET_VOID);
54 if(offMem != HGSMIOFFSET_VOID)
55 {
56 HGSMINotifyHostCmdComplete(pCtx, offMem);
57 }
58}
59
60
61/** Submit an incoming host command to the appropriate handler. */
62static void hgsmiHostCmdProcess(PHGSMIHOSTCOMMANDCONTEXT pCtx,
63 HGSMIOFFSET offBuffer)
64{
65 int rc = HGSMIBufferProcess(&pCtx->areaCtx, &pCtx->channels, offBuffer);
66 Assert(!RT_FAILURE(rc));
67 if(RT_FAILURE(rc))
68 {
69 /* failure means the command was not submitted to the handler for some reason
70 * it's our responsibility to notify its completion in this case */
71 HGSMINotifyHostCmdComplete(pCtx, offBuffer);
72 }
73 /* if the cmd succeeded it's responsibility of the callback to complete it */
74}
75
76/** Get the next command from the host. */
77static HGSMIOFFSET hgsmiGetHostBuffer(PHGSMIHOSTCOMMANDCONTEXT pCtx)
78{
79 return VBVO_PORT_READ_U32(pCtx->port);
80}
81
82
83/** Get and handle the next command from the host. */
84static void hgsmiHostCommandQueryProcess(PHGSMIHOSTCOMMANDCONTEXT pCtx)
85{
86 HGSMIOFFSET offset = hgsmiGetHostBuffer(pCtx);
87 AssertReturnVoid(offset != HGSMIOFFSET_VOID);
88 hgsmiHostCmdProcess(pCtx, offset);
89}
90
91
92/** Drain the host command queue. */
93DECLHIDDEN(void) VBoxHGSMIProcessHostQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx)
94{
95 while (pCtx->pfHostFlags->u32HostFlags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
96 {
97 if (!ASMAtomicCmpXchgBool(&pCtx->fHostCmdProcessing, true, false))
98 return;
99 hgsmiHostCommandQueryProcess(pCtx);
100 ASMAtomicWriteBool(&pCtx->fHostCmdProcessing, false);
101 }
102}
103
104
105/** Detect whether HGSMI is supported by the host. */
106DECLHIDDEN(bool) VBoxHGSMIIsSupported(void)
107{
108 uint16_t DispiId;
109
110 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
111 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_HGSMI);
112
113 DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
114
115 return (DispiId == VBE_DISPI_ID_HGSMI);
116}
117
118
119/**
120 * Allocate and initialise a command descriptor in the guest heap for a
121 * guest-to-host command.
122 *
123 * @returns pointer to the descriptor's command data buffer
124 * @param pCtx the context containing the heap to be used
125 * @param cbData the size of the command data to go into the descriptor
126 * @param u8Ch the HGSMI channel to be used, set to the descriptor
127 * @param u16Op the HGSMI command to be sent, set to the descriptor
128 */
129DECLHIDDEN(void *) VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx,
130 HGSMISIZE cbData,
131 uint8_t u8Ch,
132 uint16_t u16Op)
133{
134#ifdef VBOX_WDDM_MINIPORT
135 return VBoxSHGSMIHeapAlloc (&pCtx->heapCtx, cbData, u8Ch, u16Op);
136#else
137 return HGSMIHeapAlloc (&pCtx->heapCtx, cbData, u8Ch, u16Op);
138#endif
139}
140
141
142/**
143 * Free a descriptor allocated by @a VBoxHGSMIBufferAlloc.
144 *
145 * @param pCtx the context containing the heap used
146 * @param pvBuffer the pointer returned by @a VBoxHGSMIBufferAlloc
147 */
148DECLHIDDEN(void) VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx,
149 void *pvBuffer)
150{
151#ifdef VBOX_WDDM_MINIPORT
152 VBoxSHGSMIHeapFree (&pCtx->heapCtx, pvBuffer);
153#else
154 HGSMIHeapFree (&pCtx->heapCtx, pvBuffer);
155#endif
156}
157
158
159/**
160 * Submit a command descriptor allocated by @a VBoxHGSMIBufferAlloc.
161 *
162 * @param pCtx the context containing the heap used
163 * @param pvBuffer the pointer returned by @a VBoxHGSMIBufferAlloc
164 */
165DECLHIDDEN(int) VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx,
166 void *pvBuffer)
167{
168 /* Initialize the buffer and get the offset for port IO. */
169 HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (HGSMIGUESTCMDHEAP_GET(&pCtx->heapCtx), pvBuffer);
170
171 Assert(offBuffer != HGSMIOFFSET_VOID);
172 if (offBuffer != HGSMIOFFSET_VOID)
173 {
174 /* Submit the buffer to the host. */
175 VBVO_PORT_WRITE_U32(pCtx->port, offBuffer);
176 /* Make the compiler aware that the host has changed memory. */
177 ASMCompilerBarrier();
178 return VINF_SUCCESS;
179 }
180
181 return VERR_INVALID_PARAMETER;
182}
183
184
185/** Inform the host of the location of the host flags in VRAM via an HGSMI
186 * command. */
187static int vboxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
188 HGSMIOFFSET offLocation)
189{
190 HGSMIBUFFERLOCATION *p;
191 int rc = VINF_SUCCESS;
192
193 /* Allocate the IO buffer. */
194 p = (HGSMIBUFFERLOCATION *)VBoxHGSMIBufferAlloc(pCtx,
195 sizeof(HGSMIBUFFERLOCATION),
196 HGSMI_CH_HGSMI,
197 HGSMI_CC_HOST_FLAGS_LOCATION);
198 if (p)
199 {
200 /* Prepare data to be sent to the host. */
201 p->offLocation = offLocation;
202 p->cbLocation = sizeof(HGSMIHOSTFLAGS);
203 rc = VBoxHGSMIBufferSubmit(pCtx, p);
204 /* Free the IO buffer. */
205 VBoxHGSMIBufferFree(pCtx, p);
206 }
207 else
208 rc = VERR_NO_MEMORY;
209 return rc;
210}
211
212
213/**
214 * Inform the host of the location of the host flags in VRAM via an HGSMI
215 * command.
216 * @returns IPRT status value.
217 * @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
218 * @returns VERR_NO_MEMORY if a heap allocation fails.
219 * @param pCtx the context of the guest heap to use.
220 * @param offLocation the offset chosen for the flags withing guest
221 * VRAM.
222 */
223DECLHIDDEN(int) VBoxHGSMIReportFlagsLocation(PHGSMIGUESTCOMMANDCONTEXT pCtx,
224 HGSMIOFFSET offLocation)
225{
226 return vboxHGSMIReportFlagsLocation(pCtx, offLocation);
227}
228
229
230/** Notify the host of HGSMI-related guest capabilities via an HGSMI command.
231 */
232static int vboxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
233 uint32_t fCaps)
234{
235 VBVACAPS *pCaps;
236 int rc = VINF_SUCCESS;
237
238 /* Allocate the IO buffer. */
239 pCaps = (VBVACAPS *)VBoxHGSMIBufferAlloc(pCtx,
240 sizeof(VBVACAPS), HGSMI_CH_VBVA,
241 VBVA_INFO_CAPS);
242
243 if (pCaps)
244 {
245 /* Prepare data to be sent to the host. */
246 pCaps->rc = VERR_NOT_IMPLEMENTED;
247 pCaps->fCaps = fCaps;
248 rc = VBoxHGSMIBufferSubmit(pCtx, pCaps);
249 if (RT_SUCCESS(rc))
250 {
251 AssertRC(pCaps->rc);
252 rc = pCaps->rc;
253 }
254 /* Free the IO buffer. */
255 VBoxHGSMIBufferFree(pCtx, pCaps);
256 }
257 else
258 rc = VERR_NO_MEMORY;
259 return rc;
260}
261
262
263/**
264 * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
265 * @returns IPRT status value.
266 * @returns VERR_NOT_IMPLEMENTED if the host does not support the command.
267 * @returns VERR_NO_MEMORY if a heap allocation fails.
268 * @param pCtx the context of the guest heap to use.
269 * @param fCaps the capabilities to report, see VBVACAPS.
270 */
271DECLHIDDEN(int) VBoxHGSMISendCapsInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
272 uint32_t fCaps)
273{
274 return vboxHGSMISendCapsInfo(pCtx, fCaps);
275}
276
277
278/** Tell the host about the location of the area of VRAM set aside for the host
279 * heap. */
280static int vboxHGSMIReportHostArea(PHGSMIGUESTCOMMANDCONTEXT pCtx,
281 uint32_t u32AreaOffset, uint32_t u32AreaSize)
282{
283 VBVAINFOHEAP *p;
284 int rc = VINF_SUCCESS;
285
286 /* Allocate the IO buffer. */
287 p = (VBVAINFOHEAP *)VBoxHGSMIBufferAlloc(pCtx,
288 sizeof (VBVAINFOHEAP), HGSMI_CH_VBVA,
289 VBVA_INFO_HEAP);
290 if (p)
291 {
292 /* Prepare data to be sent to the host. */
293 p->u32HeapOffset = u32AreaOffset;
294 p->u32HeapSize = u32AreaSize;
295 rc = VBoxHGSMIBufferSubmit(pCtx, p);
296 /* Free the IO buffer. */
297 VBoxHGSMIBufferFree(pCtx, p);
298 }
299 else
300 rc = VERR_NO_MEMORY;
301 return rc;
302}
303
304
305/**
306 * Get the information needed to map the basic communication structures in
307 * device memory into our address space. All pointer parameters are optional.
308 *
309 * @param cbVRAM how much video RAM is allocated to the device
310 * @param poffVRAMBaseMapping where to save the offset from the start of the
311 * device VRAM of the whole area to map
312 * @param pcbMapping where to save the mapping size
313 * @param poffGuestHeapMemory where to save the offset into the mapped area
314 * of the guest heap backing memory
315 * @param pcbGuestHeapMemory where to save the size of the guest heap
316 * backing memory
317 * @param poffHostFlags where to save the offset into the mapped area
318 * of the host flags
319 */
320DECLHIDDEN(void) VBoxHGSMIGetBaseMappingInfo(uint32_t cbVRAM,
321 uint32_t *poffVRAMBaseMapping,
322 uint32_t *pcbMapping,
323 uint32_t *poffGuestHeapMemory,
324 uint32_t *pcbGuestHeapMemory,
325 uint32_t *poffHostFlags)
326{
327 AssertPtrNullReturnVoid(poffVRAMBaseMapping);
328 AssertPtrNullReturnVoid(pcbMapping);
329 AssertPtrNullReturnVoid(poffGuestHeapMemory);
330 AssertPtrNullReturnVoid(pcbGuestHeapMemory);
331 AssertPtrNullReturnVoid(poffHostFlags);
332 if (poffVRAMBaseMapping)
333 *poffVRAMBaseMapping = cbVRAM - VBVA_ADAPTER_INFORMATION_SIZE;
334 if (pcbMapping)
335 *pcbMapping = VBVA_ADAPTER_INFORMATION_SIZE;
336 if (poffGuestHeapMemory)
337 *poffGuestHeapMemory = 0;
338 if (pcbGuestHeapMemory)
339 *pcbGuestHeapMemory = VBVA_ADAPTER_INFORMATION_SIZE
340 - sizeof(HGSMIHOSTFLAGS);
341 if (poffHostFlags)
342 *poffHostFlags = VBVA_ADAPTER_INFORMATION_SIZE
343 - sizeof(HGSMIHOSTFLAGS);
344}
345
346
347/**
348 * Set up the HGSMI guest-to-host command context.
349 * @returns iprt status value
350 * @param pCtx the context to set up
351 * @param pvGuestHeapMemory a pointer to the mapped backing memory for
352 * the guest heap
353 * @param cbGuestHeapMemory the size of the backing memory area
354 * @param offVRAMGuestHeapMemory the offset of the memory pointed to by
355 * @a pvGuestHeapMemory within the video RAM
356 * @param pEnv HGSMI environment.
357 */
358DECLHIDDEN(int) VBoxHGSMISetupGuestContext(PHGSMIGUESTCOMMANDCONTEXT pCtx,
359 void *pvGuestHeapMemory,
360 uint32_t cbGuestHeapMemory,
361 uint32_t offVRAMGuestHeapMemory,
362 const HGSMIENV *pEnv)
363{
364 /** @todo should we be using a fixed ISA port value here? */
365 pCtx->port = (RTIOPORT)VGA_PORT_HGSMI_GUEST;
366#ifdef VBOX_WDDM_MINIPORT
367 return VBoxSHGSMIInit(&pCtx->heapCtx, pvGuestHeapMemory,
368 cbGuestHeapMemory, offVRAMGuestHeapMemory, pEnv);
369#else
370 return HGSMIHeapSetup(&pCtx->heapCtx, pvGuestHeapMemory,
371 cbGuestHeapMemory, offVRAMGuestHeapMemory, pEnv);
372#endif
373}
374
375
376/**
377 * Get the information needed to map the area used by the host to send back
378 * requests.
379 *
380 * @param pCtx the context containing the heap to use
381 * @param cbVRAM how much video RAM is allocated to the device
382 * @param offVRAMBaseMapping the offset of the basic communication structures
383 * into the guest's VRAM
384 * @param poffVRAMHostArea where to store the offset into VRAM of the host
385 * heap area
386 * @param pcbHostArea where to store the size of the host heap area
387 */
388DECLHIDDEN(void) VBoxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx,
389 uint32_t cbVRAM,
390 uint32_t offVRAMBaseMapping,
391 uint32_t *poffVRAMHostArea,
392 uint32_t *pcbHostArea)
393{
394 uint32_t offVRAMHostArea = offVRAMBaseMapping, cbHostArea = 0;
395
396 AssertPtrReturnVoid(poffVRAMHostArea);
397 AssertPtrReturnVoid(pcbHostArea);
398 VBoxQueryConfHGSMI(pCtx, VBOX_VBVA_CONF32_HOST_HEAP_SIZE, &cbHostArea);
399 if (cbHostArea != 0)
400 {
401 uint32_t cbHostAreaMaxSize = cbVRAM / 4;
402 /** @todo what is the idea of this? */
403 if (cbHostAreaMaxSize >= VBVA_ADAPTER_INFORMATION_SIZE)
404 {
405 cbHostAreaMaxSize -= VBVA_ADAPTER_INFORMATION_SIZE;
406 }
407 if (cbHostArea > cbHostAreaMaxSize)
408 {
409 cbHostArea = cbHostAreaMaxSize;
410 }
411 /* Round up to 4096 bytes. */
412 cbHostArea = (cbHostArea + 0xFFF) & ~0xFFF;
413 offVRAMHostArea = offVRAMBaseMapping - cbHostArea;
414 }
415
416 *pcbHostArea = cbHostArea;
417 *poffVRAMHostArea = offVRAMHostArea;
418 // LogFunc(("offVRAMHostArea = 0x%08X, cbHostArea = 0x%08X\n",
419 // offVRAMHostArea, cbHostArea));
420}
421
422
423/**
424 * Initialise the host context structure.
425 *
426 * @param pCtx the context structure to initialise
427 * @param pvBaseMapping where the basic HGSMI structures are mapped at
428 * @param offHostFlags the offset of the host flags into the basic HGSMI
429 * structures
430 * @param pvHostAreaMapping where the area for the host heap is mapped at
431 * @param offVRAMHostArea offset of the host heap area into VRAM
432 * @param cbHostArea size in bytes of the host heap area
433 */
434DECLHIDDEN(void) VBoxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx,
435 void *pvBaseMapping,
436 uint32_t offHostFlags,
437 void *pvHostAreaMapping,
438 uint32_t offVRAMHostArea,
439 uint32_t cbHostArea)
440{
441 uint8_t *pu8HostFlags = ((uint8_t *)pvBaseMapping) + offHostFlags;
442 pCtx->pfHostFlags = (HGSMIHOSTFLAGS *)pu8HostFlags;
443 /** @todo should we really be using a fixed ISA port value here? */
444 pCtx->port = (RTIOPORT)VGA_PORT_HGSMI_HOST;
445 HGSMIAreaInitialize(&pCtx->areaCtx, pvHostAreaMapping, cbHostArea,
446 offVRAMHostArea);
447}
448
449
450/**
451 * Tell the host about the ways it can use to communicate back to us via an
452 * HGSMI command
453 *
454 * @returns iprt status value
455 * @param pCtx the context containing the heap to use
456 * @param offVRAMFlagsLocation where we wish the host to place its flags
457 * relative to the start of the VRAM
458 * @param fCaps additions HGSMI capabilities the guest
459 * supports
460 * @param offVRAMHostArea offset into VRAM of the host heap area
461 * @param cbHostArea size in bytes of the host heap area
462 */
463DECLHIDDEN(int) VBoxHGSMISendHostCtxInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
464 HGSMIOFFSET offVRAMFlagsLocation,
465 uint32_t fCaps,
466 uint32_t offVRAMHostArea,
467 uint32_t cbHostArea)
468{
469 // Log(("VBoxVideo::vboxSetupAdapterInfo\n"));
470
471 /* setup the flags first to ensure they are initialized by the time the
472 * host heap is ready */
473 int rc = vboxHGSMIReportFlagsLocation(pCtx, offVRAMFlagsLocation);
474 AssertRC(rc);
475 if (RT_SUCCESS(rc) && fCaps)
476 {
477 /* Inform about caps */
478 rc = vboxHGSMISendCapsInfo(pCtx, fCaps);
479 AssertRC(rc);
480 }
481 if (RT_SUCCESS (rc))
482 {
483 /* Report the host heap location. */
484 rc = vboxHGSMIReportHostArea(pCtx, offVRAMHostArea, cbHostArea);
485 AssertRC(rc);
486 }
487 // Log(("VBoxVideo::vboxSetupAdapterInfo finished rc = %d\n", rc));
488 return rc;
489}
490
491
492/** Sanity test on first call. We do not worry about concurrency issues. */
493static int testQueryConf(PHGSMIGUESTCOMMANDCONTEXT pCtx)
494{
495 static bool cOnce = false;
496 uint32_t ulValue = 0;
497 int rc;
498
499 if (cOnce)
500 return VINF_SUCCESS;
501 cOnce = true;
502 rc = VBoxQueryConfHGSMI(pCtx, UINT32_MAX, &ulValue);
503 if (RT_SUCCESS(rc) && ulValue == UINT32_MAX)
504 return VINF_SUCCESS;
505 cOnce = false;
506 if (RT_FAILURE(rc))
507 return rc;
508 return VERR_INTERNAL_ERROR;
509}
510
511
512/**
513 * Query the host for an HGSMI configuration parameter via an HGSMI command.
514 * @returns iprt status value
515 * @param pCtx the context containing the heap used
516 * @param u32Index the index of the parameter to query,
517 * @see VBVACONF32::u32Index
518 * @param u32DefValue defaut value
519 * @param pulValue where to store the value of the parameter on success
520 */
521DECLHIDDEN(int) VBoxQueryConfHGSMIDef(PHGSMIGUESTCOMMANDCONTEXT pCtx,
522 uint32_t u32Index, uint32_t u32DefValue, uint32_t *pulValue)
523{
524 int rc = VINF_SUCCESS;
525 VBVACONF32 *p;
526 // LogFunc(("u32Index = %d\n", u32Index));
527
528 rc = testQueryConf(pCtx);
529 if (RT_FAILURE(rc))
530 return rc;
531 /* Allocate the IO buffer. */
532 p = (VBVACONF32 *)VBoxHGSMIBufferAlloc(pCtx,
533 sizeof(VBVACONF32), HGSMI_CH_VBVA,
534 VBVA_QUERY_CONF32);
535 if (p)
536 {
537 /* Prepare data to be sent to the host. */
538 p->u32Index = u32Index;
539 p->u32Value = u32DefValue;
540 rc = VBoxHGSMIBufferSubmit(pCtx, p);
541 if (RT_SUCCESS(rc))
542 {
543 *pulValue = p->u32Value;
544 // LogFunc(("u32Value = %d\n", p->u32Value));
545 }
546 /* Free the IO buffer. */
547 VBoxHGSMIBufferFree(pCtx, p);
548 }
549 else
550 rc = VERR_NO_MEMORY;
551 // LogFunc(("rc = %d\n", rc));
552 return rc;
553}
554
555DECLHIDDEN(int) VBoxQueryConfHGSMI(PHGSMIGUESTCOMMANDCONTEXT pCtx,
556 uint32_t u32Index, uint32_t *pulValue)
557{
558 return VBoxQueryConfHGSMIDef(pCtx, u32Index, UINT32_MAX, pulValue);
559}
560
561/**
562 * Pass the host a new mouse pointer shape via an HGSMI command.
563 *
564 * @returns success or failure
565 * @param pCtx the context containing the heap to be used
566 * @param fFlags cursor flags, @see VMMDevReqMousePointer::fFlags
567 * @param cHotX horizontal position of the hot spot
568 * @param cHotY vertical position of the hot spot
569 * @param cWidth width in pixels of the cursor
570 * @param cHeight height in pixels of the cursor
571 * @param pPixels pixel data, @see VMMDevReqMousePointer for the format
572 * @param cbLength size in bytes of the pixel data
573 */
574DECLHIDDEN(int) VBoxHGSMIUpdatePointerShape(PHGSMIGUESTCOMMANDCONTEXT pCtx,
575 uint32_t fFlags,
576 uint32_t cHotX,
577 uint32_t cHotY,
578 uint32_t cWidth,
579 uint32_t cHeight,
580 uint8_t *pPixels,
581 uint32_t cbLength)
582{
583 VBVAMOUSEPOINTERSHAPE *p;
584 uint32_t cbData = 0;
585 int rc = VINF_SUCCESS;
586
587 if (fFlags & VBOX_MOUSE_POINTER_SHAPE)
588 {
589 /* Size of the pointer data: sizeof (AND mask) + sizeof (XOR_MASK) */
590 cbData = ((((cWidth + 7) / 8) * cHeight + 3) & ~3)
591 + cWidth * 4 * cHeight;
592 /* If shape is supplied, then always create the pointer visible.
593 * See comments in 'vboxUpdatePointerShape'
594 */
595 fFlags |= VBOX_MOUSE_POINTER_VISIBLE;
596 }
597 // LogFlowFunc(("cbData %d, %dx%d\n", cbData, cWidth, cHeight));
598 if (cbData > cbLength)
599 {
600 // LogFunc(("calculated pointer data size is too big (%d bytes, limit %d)\n",
601 // cbData, cbLength));
602 return VERR_INVALID_PARAMETER;
603 }
604 /* Allocate the IO buffer. */
605 p = (VBVAMOUSEPOINTERSHAPE *)VBoxHGSMIBufferAlloc(pCtx,
606 sizeof(VBVAMOUSEPOINTERSHAPE)
607 + cbData,
608 HGSMI_CH_VBVA,
609 VBVA_MOUSE_POINTER_SHAPE);
610 if (p)
611 {
612 /* Prepare data to be sent to the host. */
613 /* Will be updated by the host. */
614 p->i32Result = VINF_SUCCESS;
615 /* We have our custom flags in the field */
616 p->fu32Flags = fFlags;
617 p->u32HotX = cHotX;
618 p->u32HotY = cHotY;
619 p->u32Width = cWidth;
620 p->u32Height = cHeight;
621 if (p->fu32Flags & VBOX_MOUSE_POINTER_SHAPE)
622 /* Copy the actual pointer data. */
623 memcpy (p->au8Data, pPixels, cbData);
624 rc = VBoxHGSMIBufferSubmit(pCtx, p);
625 if (RT_SUCCESS(rc))
626 rc = p->i32Result;
627 /* Free the IO buffer. */
628 VBoxHGSMIBufferFree(pCtx, p);
629 }
630 else
631 rc = VERR_NO_MEMORY;
632 // LogFlowFunc(("rc %d\n", rc));
633 return rc;
634}
635
636
637/**
638 * Report the guest cursor position. The host may wish to use this information
639 * to re-position its own cursor (though this is currently unlikely). The
640 * current host cursor position is returned.
641 * @param pCtx The context containing the heap used.
642 * @param fReportPosition Are we reporting a position?
643 * @param x Guest cursor X position.
644 * @param y Guest cursor Y position.
645 * @param pxHost Host cursor X position is stored here. Optional.
646 * @param pyHost Host cursor Y position is stored here. Optional.
647 * @returns iprt status code.
648 * @returns VERR_NO_MEMORY HGSMI heap allocation failed.
649 */
650DECLHIDDEN(int) VBoxHGSMICursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y,
651 uint32_t *pxHost, uint32_t *pyHost)
652{
653 int rc = VINF_SUCCESS;
654 VBVACURSORPOSITION *p;
655 // Log(("%s: x=%u, y=%u\n", __PRETTY_FUNCTION__, (unsigned)x, (unsigned)y));
656
657 /* Allocate the IO buffer. */
658 p = (VBVACURSORPOSITION *)VBoxHGSMIBufferAlloc(pCtx, sizeof(VBVACURSORPOSITION), HGSMI_CH_VBVA, VBVA_CURSOR_POSITION);
659 if (p)
660 {
661 /* Prepare data to be sent to the host. */
662 p->fReportPosition = fReportPosition ? 1 : 0;
663 p->x = x;
664 p->y = y;
665 rc = VBoxHGSMIBufferSubmit(pCtx, p);
666 if (RT_SUCCESS(rc))
667 {
668 if (pxHost)
669 *pxHost = p->x;
670 if (pyHost)
671 *pyHost = p->y;
672 // Log(("%s: return: x=%u, y=%u\n", __PRETTY_FUNCTION__, (unsigned)p->x, (unsigned)p->y));
673 }
674 /* Free the IO buffer. */
675 VBoxHGSMIBufferFree(pCtx, p);
676 }
677 else
678 rc = VERR_NO_MEMORY;
679 // LogFunc(("rc = %d\n", rc));
680 return rc;
681}
682
683
684/** @todo Mouse pointer position to be read from VMMDev memory, address of the memory region
685 * can be queried from VMMDev via an IOCTL. This VMMDev memory region will contain
686 * host information which is needed by the guest.
687 *
688 * Reading will not cause a switch to the host.
689 *
690 * Have to take into account:
691 * * synchronization: host must write to the memory only from EMT,
692 * large structures must be read under flag, which tells the host
693 * that the guest is currently reading the memory (OWNER flag?).
694 * * guest writes: may be allocate a page for the host info and make
695 * the page readonly for the guest.
696 * * the information should be available only for additions drivers.
697 * * VMMDev additions driver will inform the host which version of the info it expects,
698 * host must support all versions.
699 *
700 */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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