VirtualBox

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

Last change on this file since 60300 was 60300, checked in by vboxsync, 9 years ago

bugref:8087: Additions/x11: support non-root X server: add heuristic code to the kernel driver to detect the cursor hot-spot in case we are running old user space code which does not tell us about it. In theory we could easily extend this to work with older kernel versions which did not have the hot-spot API at all, but since older versions of X.Org could not use kernel drivers by default it does not gain us much.

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

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