VirtualBox

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

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

Main/MouseImpl: do not overwrite the "supports relative" attribute on initialisation

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