97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/* $Id$ */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/** @file
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * VBoxUsbDev.h - USB device.
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2011-2012 Oracle Corporation
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync *
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * available from http://www.virtualbox.org. This file is free software;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * you can redistribute it and/or modify it under the terms of the GNU
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * General Public License (GPL) as published by the Free Software
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#ifndef ___VBoxUsbDev_h___
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#define ___VBoxUsbDev_h___
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#include "VBoxUsbCmn.h"
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#include <iprt/assert.h>
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsynctypedef struct VBOXUSB_GLOBALS
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PDRIVER_OBJECT pDrvObj;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync UNICODE_STRING RegPath;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSBRT_IDC RtIdc;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync} VBOXUSB_GLOBALS, *PVBOXUSB_GLOBALS;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncextern VBOXUSB_GLOBALS g_VBoxUsbGlobals;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/* pnp state decls */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsynctypedef enum
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_UNKNOWN = 0,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_START_PENDING,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_STARTED,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_STOP_PENDING,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_STOPPED,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_SURPRISE_REMOVED,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_REMOVE_PENDING,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_REMOVED,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE_FORSEDWORD = 0x8fffffff
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync} ENMVBOXUSB_PNPSTATE;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncAssertCompile(sizeof (ENMVBOXUSB_PNPSTATE) == sizeof (uint32_t));
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#ifdef DEBUG
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncDECLHIDDEN(VOID) vboxUsbPnPStateGbgChange(ENMVBOXUSB_PNPSTATE enmOld, ENMVBOXUSB_PNPSTATE enmNew);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync# define VBOXUSB_PNP_GBG_STATE_CHANGE(_old, _new) vboxUsbPnPStateGbgChange((_old), (_new))
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#else
f576b52b66656e7b4db2a5e44d110cc27348c6b3vboxsync# define VBOXUSB_PNP_GBG_STATE_CHANGE(_old, _new) do { } while (0)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#endif
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsynctypedef struct VBOXUSB_PNPSTATE
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync /* Current state */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync volatile ENMVBOXUSB_PNPSTATE Curr;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync /* Previous state, used to restore state info on cancell stop device */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE Prev;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync} VBOXUSB_PNPSTATE, *PVBOXUSB_PNPSTATE;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsynctypedef struct VBOXUSBDEV_DDISTATE
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync /* Lock */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KSPIN_LOCK Lock;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXDRVTOOL_REF Ref;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSB_PNPSTATE PnPState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSB_PWRSTATE PwrState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync /* current dev caps */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync DEVICE_CAPABILITIES DevCaps;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync} VBOXUSBDEV_DDISTATE, *PVBOXUSBDEV_DDISTATE;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsynctypedef struct VBOXUSBDEV_EXT
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PDEVICE_OBJECT pFDO;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PDEVICE_OBJECT pPDO;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync PDEVICE_OBJECT pLowerDO;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSBDEV_DDISTATE DdiState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync uint32_t cHandles;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSB_RT Rt;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync} VBOXUSBDEV_EXT, *PVBOXUSBDEV_EXT;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/* pnp state api */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(ENMVBOXUSB_PNPSTATE) vboxUsbPnPStateGet(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return (ENMVBOXUSB_PNPSTATE)ASMAtomicUoReadU32((volatile uint32_t*)&pDevExt->DdiState.PnPState.Curr);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(ENMVBOXUSB_PNPSTATE) vboxUsbPnPStateSet(PVBOXUSBDEV_EXT pDevExt, ENMVBOXUSB_PNPSTATE enmState)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KIRQL Irql;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE enmOldState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeAcquireSpinLock(&pDevExt->DdiState.Lock, &Irql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDevExt->DdiState.PnPState.Prev = (ENMVBOXUSB_PNPSTATE)ASMAtomicUoReadU32((volatile uint32_t*)&pDevExt->DdiState.PnPState.Curr);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ASMAtomicWriteU32((volatile uint32_t*)&pDevExt->DdiState.PnPState.Curr, (uint32_t)enmState);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDevExt->DdiState.PnPState.Curr = enmState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync enmOldState = pDevExt->DdiState.PnPState.Prev;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeReleaseSpinLock(&pDevExt->DdiState.Lock, Irql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSB_PNP_GBG_STATE_CHANGE(enmOldState, enmState);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return enmState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(ENMVBOXUSB_PNPSTATE) vboxUsbPnPStateRestore(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE enmNewState, enmOldState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KIRQL Irql;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeAcquireSpinLock(&pDevExt->DdiState.Lock, &Irql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync enmOldState = pDevExt->DdiState.PnPState.Curr;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync enmNewState = pDevExt->DdiState.PnPState.Prev;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ASMAtomicWriteU32((volatile uint32_t*)&pDevExt->DdiState.PnPState.Curr, (uint32_t)pDevExt->DdiState.PnPState.Prev);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeReleaseSpinLock(&pDevExt->DdiState.Lock, Irql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBOXUSB_PNP_GBG_STATE_CHANGE(enmOldState, enmNewState);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(enmNewState == ENMVBOXUSB_PNPSTATE_STARTED);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync Assert(enmOldState == ENMVBOXUSB_PNPSTATE_STOP_PENDING
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync || enmOldState == ENMVBOXUSB_PNPSTATE_REMOVE_PENDING);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return enmNewState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(VOID) vboxUsbPnPStateInit(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync pDevExt->DdiState.PnPState.Curr = pDevExt->DdiState.PnPState.Prev = ENMVBOXUSB_PNPSTATE_START_PENDING;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(VOID) vboxUsbDdiStateInit(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeInitializeSpinLock(&pDevExt->DdiState.Lock);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefInit(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync vboxUsbPwrStateInit(pDevExt);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync vboxUsbPnPStateInit(pDevExt);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(bool) vboxUsbDdiStateRetainIfStarted(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KIRQL oldIrql;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync bool bRetained = true;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeAcquireSpinLock(&pDevExt->DdiState.Lock, &oldIrql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (vboxUsbPnPStateGet(pDevExt) == ENMVBOXUSB_PNPSTATE_STARTED)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefRetain(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync else
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync bRetained = false;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeReleaseSpinLock(&pDevExt->DdiState.Lock, oldIrql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return bRetained;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync/* if device is removed - does nothing and returns zero,
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * otherwise increments a ref counter and returns the current pnp state
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * NOTE: never returns ENMVBOXUSB_PNPSTATE_REMOVED
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync * */
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(ENMVBOXUSB_PNPSTATE) vboxUsbDdiStateRetainIfNotRemoved(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KIRQL oldIrql;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync ENMVBOXUSB_PNPSTATE enmState;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeAcquireSpinLock(&pDevExt->DdiState.Lock, &oldIrql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync enmState = vboxUsbPnPStateGet(pDevExt);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync if (enmState != ENMVBOXUSB_PNPSTATE_REMOVED)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync {
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefRetain(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync }
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync KeReleaseSpinLock(&pDevExt->DdiState.Lock, oldIrql);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return enmState != ENMVBOXUSB_PNPSTATE_REMOVED ? enmState : (ENMVBOXUSB_PNPSTATE)0;
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(uint32_t) vboxUsbDdiStateRetain(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return VBoxDrvToolRefRetain(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(uint32_t) vboxUsbDdiStateRelease(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync return VBoxDrvToolRefRelease(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(VOID) vboxUsbDdiStateReleaseAndWaitCompleted(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefRelease(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefWaitEqual(&pDevExt->DdiState.Ref, 1);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsyncstatic DECLINLINE(VOID) vboxUsbDdiStateReleaseAndWaitRemoved(PVBOXUSBDEV_EXT pDevExt)
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync{
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefRelease(&pDevExt->DdiState.Ref);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync VBoxDrvToolRefWaitEqual(&pDevExt->DdiState.Ref, 0);
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync}
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync
97b634ea021fd984782256de4ba4ff31cdb96c47vboxsync#endif /* #ifndef ___VBoxUsbDev_h___ */