VirtualBox

source: vbox/trunk/src/VBox/Main/MouseImpl.cpp@ 26750

Last change on this file since 26750 was 26750, checked in by vboxsync, 15 years ago

Main/MouseImpl: hopefully fix assertions in the absolute PS/2 device code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.8 KB
Line 
1/* $Id: MouseImpl.cpp 26750 2010-02-24 14:46:25Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "MouseImpl.h"
23#include "DisplayImpl.h"
24#include "VMMDev.h"
25
26#include "AutoCaller.h"
27#include "Logging.h"
28
29#include <VBox/pdmdrv.h>
30#include <iprt/asm.h>
31#include <VBox/VMMDev.h>
32
33/**
34 * Mouse driver instance data.
35 */
36typedef struct DRVMAINMOUSE
37{
38 /** Pointer to the mouse object. */
39 Mouse *pMouse;
40 /** Pointer to the driver instance structure. */
41 PPDMDRVINS pDrvIns;
42 /** Pointer to the mouse port interface of the driver/device above us. */
43 PPDMIMOUSEPORT pUpPort;
44 /** Our mouse connector interface. */
45 PDMIMOUSECONNECTOR IConnector;
46} DRVMAINMOUSE, *PDRVMAINMOUSE;
47
48
49// constructor / destructor
50/////////////////////////////////////////////////////////////////////////////
51
52DEFINE_EMPTY_CTOR_DTOR (Mouse)
53
54HRESULT Mouse::FinalConstruct()
55{
56 mpDrv = NULL;
57 mLastAbsX = 0x8000;
58 mLastAbsY = 0x8000;
59 mLastButtons = 0;
60 return S_OK;
61}
62
63void Mouse::FinalRelease()
64{
65 uninit();
66}
67
68// public methods only for internal purposes
69/////////////////////////////////////////////////////////////////////////////
70
71/**
72 * Initializes the mouse object.
73 *
74 * @returns COM result indicator
75 * @param parent handle of our parent object
76 */
77HRESULT Mouse::init (Console *parent)
78{
79 LogFlowThisFunc(("\n"));
80
81 ComAssertRet(parent, E_INVALIDARG);
82
83 /* Enclose the state transition NotReady->InInit->Ready */
84 AutoInitSpan autoInitSpan(this);
85 AssertReturn(autoInitSpan.isOk(), E_FAIL);
86
87 unconst(mParent) = parent;
88
89#ifdef RT_OS_L4
90 /* L4 console has no own mouse cursor */
91 uHostCaps = VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER;
92#else
93 uHostCaps = 0;
94#endif
95 uDevCaps = 0;
96
97 /* Confirm a successful initialization */
98 autoInitSpan.setSucceeded();
99
100 return S_OK;
101}
102
103/**
104 * Uninitializes the instance and sets the ready flag to FALSE.
105 * Called either from FinalRelease() or by the parent when it gets destroyed.
106 */
107void Mouse::uninit()
108{
109 LogFlowThisFunc(("\n"));
110
111 /* Enclose the state transition Ready->InUninit->NotReady */
112 AutoUninitSpan autoUninitSpan(this);
113 if (autoUninitSpan.uninitDone())
114 return;
115
116 if (mpDrv)
117 mpDrv->pMouse = NULL;
118 mpDrv = NULL;
119
120 unconst(mParent).setNull();
121}
122
123
124// IMouse properties
125/////////////////////////////////////////////////////////////////////////////
126
127int Mouse::getVMMDevMouseCaps(uint32_t *pfCaps)
128{
129 AssertPtrReturn(pfCaps, E_POINTER);
130 VMMDev *pVMMDev = mParent->getVMMDev();
131 ComAssertRet(pVMMDev, E_FAIL);
132 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
133 ComAssertRet(pVMMDevPort, E_FAIL);
134
135 int rc = pVMMDevPort->pfnQueryMouseCapabilities(pVMMDevPort, pfCaps);
136 return RT_SUCCESS(rc) ? S_OK : E_FAIL;
137}
138
139int Mouse::setVMMDevMouseCaps(uint32_t fCaps)
140{
141 VMMDev *pVMMDev = mParent->getVMMDev();
142 ComAssertRet(pVMMDev, E_FAIL);
143 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
144 ComAssertRet(pVMMDevPort, E_FAIL);
145
146 int rc = pVMMDevPort->pfnSetMouseCapabilities(pVMMDevPort, fCaps);
147 return RT_SUCCESS(rc) ? S_OK : E_FAIL;
148}
149
150/**
151 * Returns whether the current setup can accept absolute mouse
152 * events.
153 *
154 * @returns COM status code
155 * @param absoluteSupported address of result variable
156 */
157STDMETHODIMP Mouse::COMGETTER(AbsoluteSupported) (BOOL *absoluteSupported)
158{
159 if (!absoluteSupported)
160 return E_POINTER;
161
162 AutoCaller autoCaller(this);
163 if (FAILED(autoCaller.rc())) return autoCaller.rc();
164
165 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
166
167 CHECK_CONSOLE_DRV (mpDrv);
168
169 if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE)
170 *absoluteSupported = TRUE;
171 else
172 {
173 uint32_t mouseCaps;
174 int rc = getVMMDevMouseCaps(&mouseCaps);
175 AssertComRCReturn(rc, rc);
176 *absoluteSupported = mouseCaps & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE;
177 }
178
179 return S_OK;
180}
181
182/**
183 * Returns whether the guest can currently draw the mouse cursor itself.
184 *
185 * @returns COM status code
186 * @param absoluteSupported address of result variable
187 */
188STDMETHODIMP Mouse::COMGETTER(NeedsHostCursor) (BOOL *pfNeedsHostCursor)
189{
190 if (!pfNeedsHostCursor)
191 return E_POINTER;
192
193 AutoCaller autoCaller(this);
194 if (FAILED(autoCaller.rc())) return autoCaller.rc();
195
196 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
197
198 CHECK_CONSOLE_DRV (mpDrv);
199
200 uint32_t fMouseCaps;
201 int rc = getVMMDevMouseCaps(&fMouseCaps);
202 AssertComRCReturn(rc, rc);
203 *pfNeedsHostCursor = !!( fMouseCaps
204 & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
205 return S_OK;
206}
207
208// IMouse methods
209/////////////////////////////////////////////////////////////////////////////
210
211static uint32_t mouseButtonsToPDM(LONG buttonState)
212{
213 uint32_t fButtons = 0;
214 if (buttonState & MouseButtonState_LeftButton)
215 fButtons |= PDMIMOUSEPORT_BUTTON_LEFT;
216 if (buttonState & MouseButtonState_RightButton)
217 fButtons |= PDMIMOUSEPORT_BUTTON_RIGHT;
218 if (buttonState & MouseButtonState_MiddleButton)
219 fButtons |= PDMIMOUSEPORT_BUTTON_MIDDLE;
220 if (buttonState & MouseButtonState_XButton1)
221 fButtons |= PDMIMOUSEPORT_BUTTON_X1;
222 if (buttonState & MouseButtonState_XButton2)
223 fButtons |= PDMIMOUSEPORT_BUTTON_X2;
224 return fButtons;
225}
226
227
228/**
229 * Send a relative event to the mouse device.
230 *
231 * @returns COM status code
232 */
233int Mouse::reportRelEventToMouseDev(int32_t dx, int32_t dy, int32_t dz,
234 int32_t dw, uint32_t fButtons)
235{
236 if (dx || dy || dz || dw || fButtons != mLastButtons)
237 {
238 PPDMIMOUSEPORT pUpPort = mpDrv->pUpPort;
239 int vrc = pUpPort->pfnPutEvent(pUpPort, dx, dy, dz, dw, fButtons);
240
241 if (RT_FAILURE(vrc))
242 setError(VBOX_E_IPRT_ERROR,
243 tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
244 vrc);
245 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR);
246 }
247 return S_OK;
248}
249
250
251/**
252 * Send an absolute position event to the mouse device.
253 *
254 * @returns COM status code
255 */
256int Mouse::reportAbsEventToMouseDev(uint32_t mouseXAbs, uint32_t mouseYAbs,
257 int32_t dz, int32_t dw, uint32_t fButtons)
258{
259 if ( mouseXAbs != mLastAbsX
260 || mouseYAbs != mLastAbsY
261 || dz
262 || dw
263 || fButtons != mLastButtons)
264 {
265 int vrc = mpDrv->pUpPort->pfnPutEventAbs(mpDrv->pUpPort, mouseXAbs,
266 mouseYAbs, dz, dw, fButtons);
267 if (RT_FAILURE(vrc))
268 setError(VBOX_E_IPRT_ERROR,
269 tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
270 vrc);
271 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR);
272 }
273 return S_OK;
274}
275
276
277/**
278 * Send an absolute position event to the VMM device.
279 *
280 * @returns COM status code
281 */
282int Mouse::reportAbsEventToVMMDev(uint32_t mouseXAbs, uint32_t mouseYAbs)
283{
284 VMMDev *pVMMDev = mParent->getVMMDev();
285 ComAssertRet(pVMMDev, E_FAIL);
286 PPDMIVMMDEVPORT pVMMDevPort = pVMMDev->getVMMDevPort();
287 ComAssertRet(pVMMDevPort, E_FAIL);
288
289 if (mouseXAbs != mLastAbsX || mouseYAbs != mLastAbsY)
290 {
291 int vrc = pVMMDevPort->pfnSetAbsoluteMouse(pVMMDevPort,
292 mouseXAbs, mouseYAbs);
293 if (RT_FAILURE(vrc))
294 setError(VBOX_E_IPRT_ERROR,
295 tr("Could not send the mouse event to the virtual mouse (%Rrc)"),
296 vrc);
297 AssertRCReturn(vrc, VBOX_E_IPRT_ERROR);
298 }
299 return S_OK;
300}
301
302/**
303 * Send a mouse event.
304 *
305 * @returns COM status code
306 * @param dx X movement
307 * @param dy Y movement
308 * @param dz Z movement
309 * @param buttonState The mouse button state
310 */
311STDMETHODIMP Mouse::PutMouseEvent(LONG dx, LONG dy, LONG dz, LONG dw, LONG buttonState)
312{
313 HRESULT rc = S_OK;
314
315 AutoCaller autoCaller(this);
316 if (FAILED(autoCaller.rc())) return autoCaller.rc();
317
318 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
319
320 CHECK_CONSOLE_DRV (mpDrv);
321
322 LogRel3(("%s: dx=%d, dy=%d, dz=%d, dw=%d\n", __PRETTY_FUNCTION__,
323 dx, dy, dz, dw));
324 if (!(uDevCaps & MOUSE_DEVCAP_ABSOLUTE))
325 {
326 /*
327 * This method being called implies that the host no
328 * longer wants to use absolute coordinates. If the VMM
329 * device isn't aware of that yet, tell it.
330 */
331 uint32_t mouseCaps;
332 rc = getVMMDevMouseCaps(&mouseCaps);
333 ComAssertComRCRet(rc, rc);
334
335 if (mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)
336 setVMMDevMouseCaps(uHostCaps);
337 }
338
339 uint32_t fButtons = mouseButtonsToPDM(buttonState);
340 rc = reportRelEventToMouseDev(dx, dy, dz, dw, fButtons);
341 if (SUCCEEDED(rc))
342 mLastButtons = fButtons;
343
344 return rc;
345}
346
347/**
348 * Convert an X value in screen co-ordinates to a value from 0 to 0xffff
349 *
350 * @returns COM status value
351 */
352int Mouse::convertDisplayWidth(LONG x, uint32_t *pcX)
353{
354 AssertPtrReturn(pcX, E_POINTER);
355 Display *pDisplay = mParent->getDisplay();
356 ComAssertRet(pDisplay, E_FAIL);
357
358 ULONG displayWidth;
359 int rc = pDisplay->COMGETTER(Width)(&displayWidth);
360 ComAssertComRCRet(rc, rc);
361
362 *pcX = displayWidth ? (x * 0xFFFF) / displayWidth: 0;
363 return S_OK;
364}
365
366/**
367 * Convert a Y value in screen co-ordinates to a value from 0 to 0xffff
368 *
369 * @returns COM status value
370 */
371int Mouse::convertDisplayHeight(LONG y, uint32_t *pcY)
372{
373 AssertPtrReturn(pcY, E_POINTER);
374 Display *pDisplay = mParent->getDisplay();
375 ComAssertRet(pDisplay, E_FAIL);
376
377 ULONG displayHeight;
378 int rc = pDisplay->COMGETTER(Height)(&displayHeight);
379 ComAssertComRCRet(rc, rc);
380
381 *pcY = displayHeight ? (y * 0xFFFF) / displayHeight: 0;
382 return S_OK;
383}
384
385
386/**
387 * Send an absolute mouse event to the VM. This only works
388 * when the required guest support has been installed.
389 *
390 * @returns COM status code
391 * @param x X position (pixel)
392 * @param y Y position (pixel)
393 * @param dz Z movement
394 * @param buttonState The mouse button state
395 */
396STDMETHODIMP Mouse::PutMouseEventAbsolute(LONG x, LONG y, LONG dz, LONG dw,
397 LONG buttonState)
398{
399 AutoCaller autoCaller(this);
400 if (FAILED(autoCaller.rc())) return autoCaller.rc();
401
402 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
403
404 LogRel3(("%s: x=%d, y=%d, dz=%d, dw=%d, buttonState=0x%x\n",
405 __PRETTY_FUNCTION__, x, y, dz, dw, buttonState));
406
407 CHECK_CONSOLE_DRV(mpDrv);
408
409 uint32_t mouseXAbs;
410 HRESULT rc = convertDisplayWidth(x, &mouseXAbs);
411 ComAssertComRCRet(rc, rc);
412 if (mouseXAbs > 0xffff)
413 mouseXAbs = mLastAbsX;
414
415 uint32_t mouseYAbs;
416 rc = convertDisplayHeight(y, &mouseYAbs);
417 ComAssertComRCRet(rc, rc);
418 if (mouseYAbs > 0xffff)
419 mouseYAbs = mLastAbsY;
420
421 uint32_t fButtons = mouseButtonsToPDM(buttonState);
422
423 /* Older guest additions rely on a small phony movement event on the
424 * PS/2 device to notice absolute events. */
425 bool fNeedsJiggle = false;
426
427 if (uDevCaps & MOUSE_DEVCAP_ABSOLUTE)
428 rc = reportAbsEventToMouseDev(mouseXAbs, mouseYAbs, dz, dw, fButtons);
429 else
430 {
431 uint32_t mouseCaps;
432 rc = getVMMDevMouseCaps(&mouseCaps);
433 ComAssertComRCRet(rc, rc);
434
435 /*
436 * This method being called implies that the host wants
437 * to use absolute coordinates. If the VMM device isn't
438 * aware of that yet, tell it.
439 */
440 if (!(mouseCaps & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE))
441 setVMMDevMouseCaps(uHostCaps | VMMDEV_MOUSE_HOST_CAN_ABSOLUTE);
442
443 /*
444 * Send the absolute mouse position to the VMM device.
445 */
446 rc = reportAbsEventToVMMDev(mouseXAbs, mouseYAbs);
447 fNeedsJiggle = !(mouseCaps & VMMDEV_MOUSE_GUEST_USES_VMMDEV);
448 }
449 ComAssertComRCRet(rc, rc);
450
451 mLastAbsX = mouseXAbs;
452 mLastAbsY = mouseYAbs;
453
454 if (!(uDevCaps & MOUSE_DEVCAP_ABSOLUTE))
455 {
456 /* We may need to send a relative event for button information or to
457 * wake the guest up to the changed absolute co-ordinates.
458 * If the event is a pure wake up one, we make sure it contains some
459 * (possibly phony) event data to make sure it isn't just discarded on
460 * the way. */
461 if (fNeedsJiggle || fButtons != mLastButtons || dz || dw)
462 {
463 rc = reportRelEventToMouseDev(fNeedsJiggle ? 1 : 0, 0, dz, dw,
464 fButtons);
465 ComAssertComRCRet(rc, rc);
466 }
467 }
468 mLastButtons = fButtons;
469 return rc;
470}
471
472// private methods
473/////////////////////////////////////////////////////////////////////////////
474
475
476/**
477 * @interface_method_impl{PDMIMOUSECONNECTOR,pfnAbsModeChange}
478 */
479DECLCALLBACK(void) Mouse::mouseAbsModeChange(PPDMIMOUSECONNECTOR pInterface, bool fEnabled)
480{
481 PDRVMAINMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVMAINMOUSE, IConnector);
482 if (fEnabled)
483 pDrv->pMouse->uDevCaps |= MOUSE_DEVCAP_ABSOLUTE;
484 else
485 pDrv->pMouse->uDevCaps &= ~MOUSE_DEVCAP_ABSOLUTE;
486
487 /** @todo we have to hack around the fact that VMMDev may not be
488 * initialised too close to startup. The real fix is to change the
489 * protocol for onMouseCapabilityChange so that we no longer need to
490 * query VMMDev, but that requires more changes that I want to do in
491 * the next commit, so it must be put off until the followup one. */
492 uint32_t fMouseCaps = 0;
493 int rc = S_OK;
494 if ( pDrv->pMouse->mParent->getVMMDev()
495 && pDrv->pMouse->mParent->getVMMDev()->mpDrv)
496 rc = pDrv->pMouse->getVMMDevMouseCaps(&fMouseCaps);
497 AssertComRCReturnVoid(rc);
498 pDrv->pMouse->getParent()->onMouseCapabilityChange(fEnabled, fMouseCaps & VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
499}
500
501
502/**
503 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
504 */
505DECLCALLBACK(void *) Mouse::drvQueryInterface(PPDMIBASE pInterface, const char *pszIID)
506{
507 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
508 PDRVMAINMOUSE pDrv = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
509
510 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
511 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pDrv->IConnector);
512 return NULL;
513}
514
515
516/**
517 * Destruct a mouse driver instance.
518 *
519 * @returns VBox status.
520 * @param pDrvIns The driver instance data.
521 */
522DECLCALLBACK(void) Mouse::drvDestruct(PPDMDRVINS pDrvIns)
523{
524 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
525 LogFlow(("Mouse::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
526 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
527
528 if (pData->pMouse)
529 {
530 AutoWriteLock mouseLock(pData->pMouse COMMA_LOCKVAL_SRC_POS);
531 pData->pMouse->mpDrv = NULL;
532 }
533}
534
535
536/**
537 * Construct a mouse driver instance.
538 *
539 * @copydoc FNPDMDRVCONSTRUCT
540 */
541DECLCALLBACK(int) Mouse::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
542{
543 PDRVMAINMOUSE pData = PDMINS_2_DATA(pDrvIns, PDRVMAINMOUSE);
544 LogFlow(("drvMainMouse_Construct: iInstance=%d\n", pDrvIns->iInstance));
545 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
546
547 /*
548 * Validate configuration.
549 */
550 if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
551 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
552 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
553 ("Configuration error: Not possible to attach anything to this driver!\n"),
554 VERR_PDM_DRVINS_NO_ATTACH);
555
556 /*
557 * IBase.
558 */
559 pDrvIns->IBase.pfnQueryInterface = Mouse::drvQueryInterface;
560
561 pData->IConnector.pfnAbsModeChange = Mouse::mouseAbsModeChange;
562
563 /*
564 * Get the IMousePort interface of the above driver/device.
565 */
566 pData->pUpPort = (PPDMIMOUSEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMIMOUSEPORT_IID);
567 if (!pData->pUpPort)
568 {
569 AssertMsgFailed(("Configuration error: No mouse port interface above!\n"));
570 return VERR_PDM_MISSING_INTERFACE_ABOVE;
571 }
572
573 /*
574 * Get the Mouse object pointer and update the mpDrv member.
575 */
576 void *pv;
577 int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
578 if (RT_FAILURE(rc))
579 {
580 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
581 return rc;
582 }
583 pData->pMouse = (Mouse *)pv; /** @todo Check this cast! */
584 pData->pMouse->mpDrv = pData;
585
586 return VINF_SUCCESS;
587}
588
589
590/**
591 * Main mouse driver registration record.
592 */
593const PDMDRVREG Mouse::DrvReg =
594{
595 /* u32Version */
596 PDM_DRVREG_VERSION,
597 /* szName */
598 "MainMouse",
599 /* szRCMod */
600 "",
601 /* szR0Mod */
602 "",
603 /* pszDescription */
604 "Main mouse driver (Main as in the API).",
605 /* fFlags */
606 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
607 /* fClass. */
608 PDM_DRVREG_CLASS_MOUSE,
609 /* cMaxInstances */
610 ~0,
611 /* cbInstance */
612 sizeof(DRVMAINMOUSE),
613 /* pfnConstruct */
614 Mouse::drvConstruct,
615 /* pfnDestruct */
616 Mouse::drvDestruct,
617 /* pfnRelocate */
618 NULL,
619 /* pfnIOCtl */
620 NULL,
621 /* pfnPowerOn */
622 NULL,
623 /* pfnReset */
624 NULL,
625 /* pfnSuspend */
626 NULL,
627 /* pfnResume */
628 NULL,
629 /* pfnAttach */
630 NULL,
631 /* pfnDetach */
632 NULL,
633 /* pfnPowerOff */
634 NULL,
635 /* pfnSoftReset */
636 NULL,
637 /* u32EndVersion */
638 PDM_DRVREG_VERSION
639};
640/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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