summaryrefslogtreecommitdiff
path: root/usb/umdf_fx2/driver
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-04-29 09:48:49 -0700
committerDave Wilson <[email protected]>2015-04-29 10:47:29 -0700
commitd40232638faaab19de557e70a3ee938da7a35295 (patch)
tree14e61c973745949af186b7940e3a53d25322f5de /usb/umdf_fx2/driver
parent02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff)
samples update for //build
Diffstat (limited to 'usb/umdf_fx2/driver')
-rw-r--r--usb/umdf_fx2/driver/ControlQueue.cpp564
-rw-r--r--usb/umdf_fx2/driver/ControlQueue.h101
-rw-r--r--usb/umdf_fx2/driver/Device.cpp2087
-rw-r--r--usb/umdf_fx2/driver/Device.h604
-rw-r--r--usb/umdf_fx2/driver/Driver.cpp220
-rw-r--r--usb/umdf_fx2/driver/Driver.h149
-rw-r--r--usb/umdf_fx2/driver/OsrUsbFx2.ctl1
-rw-r--r--usb/umdf_fx2/driver/OsrUsbFx2.rc21
-rw-r--r--usb/umdf_fx2/driver/ReadWriteQueue.cpp425
-rw-r--r--usb/umdf_fx2/driver/ReadWriteQueue.h163
-rw-r--r--usb/umdf_fx2/driver/WUDFOsrUsbFx2.inx115
-rw-r--r--usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj319
-rw-r--r--usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj.Filters60
-rw-r--r--usb/umdf_fx2/driver/comsup.cpp344
-rw-r--r--usb/umdf_fx2/driver/comsup.h215
-rw-r--r--usb/umdf_fx2/driver/dllsup.cpp202
-rw-r--r--usb/umdf_fx2/driver/exports.def4
-rw-r--r--usb/umdf_fx2/driver/internal.h170
-rw-r--r--usb/umdf_fx2/driver/queue.cpp147
-rw-r--r--usb/umdf_fx2/driver/queue.h93
20 files changed, 6004 insertions, 0 deletions
diff --git a/usb/umdf_fx2/driver/ControlQueue.cpp b/usb/umdf_fx2/driver/ControlQueue.cpp
new file mode 100644
index 00000000..f4058941
--- /dev/null
+++ b/usb/umdf_fx2/driver/ControlQueue.cpp
@@ -0,0 +1,564 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ControlQueue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs
+ the ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+
+#include "winioctl.h"
+
+#include "ControlQueue.tmh"
+
+CMyControlQueue::CMyControlQueue(
+ _In_ PCMyDevice Device
+ ) : CMyQueue(Device)
+{
+
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CMyControlQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+Routine Description:
+
+
+ Query Interface
+
+Aruments:
+
+ Follows COM specifications
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ HRESULT hr;
+
+
+ if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackDeviceIoControl)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackDeviceIoControl();
+
+ }
+ else
+ {
+ hr = CMyQueue::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+//
+// Initialize
+//
+
+HRESULT
+CMyControlQueue::CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyControlQueue *Queue
+ )
+/*++
+
+Routine Description:
+
+
+ CreateInstance creates an instance of the queue object.
+
+Aruments:
+
+ ppUkwn - OUT parameter is an IUnknown interface to the queue object
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ PCMyControlQueue queue = NULL;
+ HRESULT hr = S_OK;
+
+ queue = new CMyControlQueue(Device);
+
+ if (NULL == queue)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Call the queue callback object to initialize itself. This will create
+ // its partner queue framework object.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = queue->Initialize();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *Queue = queue;
+ }
+ else
+ {
+ SAFE_RELEASE(queue);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyControlQueue::Initialize(
+ VOID
+ )
+{
+ HRESULT hr;
+
+ //
+ // First initialize the base class. This will create the partner FxIoQueue
+ // object and setup automatic forwarding of I/O controls.
+ //
+
+ //
+ // The framework (UMDF) will not deliver a
+ // request to the driver that arrives on a power-managed queue, unless
+ // the device is in a powered-up state. If you receive a request on a
+ // power-managed queue after the device has idled out,
+ // the framework will not be able to power-up and present the request
+ // to the driver unless it is the power policy owner (PPO).
+ // Since this driver is the PPO it can use power managed queues
+ //
+
+ hr = __super::Initialize(WdfIoQueueDispatchSequential,
+ false,
+ true /* use power managed queue */);
+
+ //
+ // return the status.
+ //
+
+ return hr;
+}
+
+VOID
+STDMETHODCALLTYPE
+CMyControlQueue::OnDeviceIoControl(
+ _In_ IWDFIoQueue *FxQueue,
+ _In_ IWDFIoRequest *FxRequest,
+ _In_ ULONG ControlCode,
+ _In_ SIZE_T InputBufferSizeInBytes,
+ _In_ SIZE_T OutputBufferSizeInBytes
+ )
+/*++
+
+Routine Description:
+
+
+ DeviceIoControl dispatch routine
+
+Aruments:
+
+ FxQueue - Framework Queue instance
+ FxRequest - Framework Request instance
+ ControlCode - IO Control Code
+ InputBufferSizeInBytes - Lenth of input buffer
+ OutputBufferSizeInBytes - Lenth of output buffer
+
+ Always succeeds DeviceIoIoctl
+Return Value:
+
+ VOID
+
+--*/
+{
+ UNREFERENCED_PARAMETER(FxQueue);
+
+ IWDFMemory *memory = NULL;
+ PVOID buffer;
+
+ SIZE_T bigBufferCb;
+
+ ULONG information = 0;
+
+ bool completeRequest = true;
+
+ HRESULT hr = S_OK;
+
+ switch (ControlCode)
+ {
+ case IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR:
+ {
+ //
+ // Get the output buffer.
+ //
+
+ FxRequest->GetOutputMemory(&memory );
+
+ //
+ // request the descriptor.
+ //
+
+ ULONG bufferCb;
+
+ //
+ // Get the buffer address then release the memory object.
+ // The memory object remains valid until the request is
+ // completed.
+ //
+
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ if (bigBufferCb > ULONG_MAX)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ break;
+ }
+ else
+ {
+ bufferCb = (ULONG) bigBufferCb;
+ }
+
+ hr = m_Device->GetUsbTargetDevice()->RetrieveDescriptor(
+ USB_CONFIGURATION_DESCRIPTOR_TYPE,
+ 0,
+ 0,
+ &bufferCb,
+ (PUCHAR) buffer
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ information = bufferCb;
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the result of the
+ // control transfer.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(BAR_GRAPH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetOutputMemory(&memory );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->GetBarGraphDisplay((PBAR_GRAPH_STATE) buffer);
+ }
+
+ //
+ // If that worked then record how many bytes of data we're
+ // returning.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ information = sizeof(BAR_GRAPH_STATE);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the input for the
+ // control transfer.
+ //
+
+ if (InputBufferSizeInBytes < sizeof(BAR_GRAPH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetInputMemory(&memory);
+ }
+
+ //
+ // Get the data buffer and use it to set the bar graph on the
+ // device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->SetBarGraphDisplay((PBAR_GRAPH_STATE) buffer);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the result of the
+ // control transfer.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(SEVEN_SEGMENT))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetOutputMemory(&memory );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+ hr = m_Device->GetSevenSegmentDisplay((PSEVEN_SEGMENT) buffer);
+ }
+
+ //
+ // If that worked then record how many bytes of data we're
+ // returning.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ information = sizeof(SEVEN_SEGMENT);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY:
+ {
+ //
+ // Make sure the buffer is big enough to hold the input for the
+ // control transfer.
+ //
+
+ if (InputBufferSizeInBytes < sizeof(SEVEN_SEGMENT))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetInputMemory(&memory );
+ }
+
+ //
+ // Get the data buffer and use it to set the bar graph on the
+ // device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->SetSevenSegmentDisplay((PSEVEN_SEGMENT) buffer);
+ }
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_READ_SWITCHES:
+ {
+ //
+ // Make sure the buffer is big enough to hold the input for the
+ // control transfer.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(SWITCH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ FxRequest->GetOutputMemory(&memory );
+ }
+
+ //
+ // Get the data buffer and use it to set the bar graph on the
+ // device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ buffer = memory->GetDataBuffer(&bigBufferCb);
+ memory->Release();
+
+ hr = m_Device->ReadSwitchState((PSWITCH_STATE) buffer);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ information = sizeof(SWITCH_STATE);
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE:
+ {
+ //
+ // Make sure the buffer is big enough to hold the switch
+ // state.
+ //
+
+ if (OutputBufferSizeInBytes < sizeof(SWITCH_STATE))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ //
+ // Forward the request to the switch state change queue.
+ //
+
+ hr = FxRequest->ForwardToIoQueue(
+ m_Device->GetSwitchChangeQueue()
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ completeRequest = false;
+ }
+ }
+
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_RESET_DEVICE:
+ case IOCTL_OSRUSBFX2_REENUMERATE_DEVICE:
+ {
+ //
+ // WinUSB does not allow us to reset or re-enumerate the device.
+ // Return not-supported for the error in both of these cases.
+ //
+
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+ break;
+ }
+
+ case IOCTL_OSRUSBFX2_PLAY_FILE:
+ {
+ //
+ // This IOCTL demonstrates how to use impersonation to access
+ // resources using the credentials provided by the client. Note
+ // that for impersonation to work it has to be enabled in the device
+ // INF and the client must allow impersonation when they open the
+ // device.
+ //
+ // This IOCTL opens a file using the path provided by the client
+ // and then plays the characters in that file out to the seven segment
+ // display in a worker thread.
+ //
+
+ PFILE_PLAYBACK playback;
+ SIZE_T playbackCb;
+ size_t realPlaybackCb;
+
+ FxRequest->GetInputMemory(&memory);
+
+ if (memory == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+
+ //
+ // Get the playback structure from the input buffer.
+ //
+
+ playback = (PFILE_PLAYBACK) memory->GetDataBuffer(&playbackCb);
+
+ memory->Release();
+
+ //
+ // Make sure the length is at least as big as the fixed portion
+ // of the input structure.
+ //
+
+ if (playbackCb < (FIELD_OFFSET(FILE_PLAYBACK, Path)))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+
+ //
+ // Make sure the file name is at least one character long.
+ //
+
+ playbackCb -= FIELD_OFFSET(FILE_PLAYBACK, Path);
+
+ if (playbackCb < sizeof(WCHAR))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ break;
+ }
+
+ //
+ // Verify that the string provided is valid.
+ //
+
+ hr = StringCbLength(playback->Path,
+ min(playbackCb, (STRSAFE_MAX_CCH * sizeof(WCHAR))),
+ &realPlaybackCb);
+
+ if (FAILED(hr))
+ {
+ break;
+ }
+
+ hr = m_Device->PlaybackFile(playback, FxRequest);
+
+ break;
+ }
+
+
+
+ default:
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
+ break;
+ }
+ }
+
+ if (completeRequest)
+ {
+ FxRequest->CompleteWithInformation(hr, information);
+ }
+
+ return;
+}
diff --git a/usb/umdf_fx2/driver/ControlQueue.h b/usb/umdf_fx2/driver/ControlQueue.h
new file mode 100644
index 00000000..251521e1
--- /dev/null
+++ b/usb/umdf_fx2/driver/ControlQueue.h
@@ -0,0 +1,101 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ControlQueue.h
+
+Abstract:
+
+ This file defines the queue callback object for handling device I/O
+ control requests. This is a serialized queue.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Queue Callback Object.
+//
+
+class CMyControlQueue : public IQueueCallbackDeviceIoControl,
+ public CMyQueue
+{
+ HRESULT
+ Initialize(
+ VOID
+ );
+
+public:
+
+ CMyControlQueue(
+ _In_ PCMyDevice Device
+ );
+
+ virtual
+ ~CMyControlQueue(
+ VOID
+ )
+ {
+ return;
+ }
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyControlQueue *Queue
+ );
+
+ HRESULT
+ Configure(
+ VOID
+ )
+ {
+ return S_OK;
+ }
+
+ IQueueCallbackDeviceIoControl *
+ QueryIQueueCallbackDeviceIoControl(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackDeviceIoControl *>(this);
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHOD_(ULONG,AddRef) (VOID) {return CUnknown::AddRef();}
+
+ _At_(this, __drv_freesMem(object))
+ STDMETHOD_(ULONG,Release) (VOID) {return CUnknown::Release();}
+
+ STDMETHOD_(HRESULT, QueryInterface)(
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ //
+ // Wdf Callbacks
+ //
+
+ //
+ // IQueueCallbackDeviceIoControl
+ //
+ STDMETHOD_ (void, OnDeviceIoControl)(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ ULONG ControlCode,
+ _In_ SIZE_T InputBufferSizeInBytes,
+ _In_ SIZE_T OutputBufferSizeInBytes
+ );
+};
+
diff --git a/usb/umdf_fx2/driver/Device.cpp b/usb/umdf_fx2/driver/Device.cpp
new file mode 100644
index 00000000..2ebf4079
--- /dev/null
+++ b/usb/umdf_fx2/driver/Device.cpp
@@ -0,0 +1,2087 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Device.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR Fx2 driver's
+ device callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+#include "internal.h"
+#include "initguid.h"
+#include "usb_hw.h"
+#include <devpkey.h>
+
+#include "device.tmh"
+#define CONCURRENT_READS 2
+
+CMyDevice::~CMyDevice(
+ )
+{
+ SAFE_RELEASE(m_pIoTargetInterruptPipeStateMgmt);
+}
+
+HRESULT
+CMyDevice::CreateInstance(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize * FxDeviceInit,
+ _Out_ PCMyDevice *Device
+ )
+/*++
+
+ Routine Description:
+
+ This method creates and initializs an instance of the OSR Fx2 driver's
+ device callback object.
+
+ Arguments:
+
+ FxDeviceInit - the settings for the device.
+
+ Device - a location to store the referenced pointer to the device object.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ PCMyDevice device;
+ HRESULT hr;
+
+ //
+ // Allocate a new instance of the device class.
+ //
+
+ device = new CMyDevice();
+
+ if (NULL == device)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the instance.
+ //
+
+ hr = device->Initialize(FxDriver, FxDeviceInit);
+
+ if (SUCCEEDED(hr))
+ {
+ *Device = device;
+ }
+ else
+ {
+ device->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::Initialize(
+ _In_ IWDFDriver * FxDriver,
+ _In_ IWDFDeviceInitialize * FxDeviceInit
+ )
+/*++
+
+ Routine Description:
+
+ This method initializes the device callback object and creates the
+ partner device object.
+
+ The method should perform any device-specific configuration that:
+ * could fail (these can't be done in the constructor)
+ * must be done before the partner object is created -or-
+ * can be done after the partner object is created and which aren't
+ influenced by any device-level parameters the parent (the driver
+ in this case) might set.
+
+ Arguments:
+
+ FxDeviceInit - the settings for this device.
+
+ Return Value:
+
+ status.
+
+--*/
+{
+ IWDFDevice2 *fxDevice = NULL;
+
+ HRESULT hr = S_OK;
+
+ //
+ // TODO: Any per-device initialization which must be done before
+ // creating the partner object.
+ //
+
+ //
+ // Set no locking unless you need an automatic callbacks synchronization
+ //
+
+ FxDeviceInit->SetLockingConstraint(None);
+
+ //
+ // TODO: If you're writing a filter driver then indicate that here.
+ // And then don't claim power policy ownership below
+ //
+ // FxDeviceInit->SetFilter();
+ //
+
+ //
+ // Set the Fx2 driver as the power policy owner.
+ //
+
+ FxDeviceInit->SetPowerPolicyOwnership(TRUE);
+
+ //
+ // Create a new FX device object and assign the new callback object to
+ // handle any device level events that occur.
+ //
+
+ //
+ // QueryIUnknown references the IUnknown interface that it returns
+ // (which is the same as referencing the device). We pass that to
+ // CreateDevice, which takes its own reference if everything works.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ IUnknown *unknown = this->QueryIUnknown();
+ IWDFDevice* device1;
+
+ hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &device1);
+
+ //
+ // Convert the interface to version 2
+ //
+
+ if (SUCCEEDED(hr)) {
+ device1->QueryInterface(IID_PPV_ARGS(&fxDevice));
+ _Analysis_assume_(fxDevice != NULL);
+ device1->Release();
+ }
+
+ unknown->Release();
+ }
+
+ //
+ // If that succeeded then set our FxDevice member variable.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice = fxDevice;
+
+ //
+ // Drop the reference we got from CreateDevice. Since this object
+ // is partnered with the framework object they have the same
+ // lifespan - there is no need for an additional reference.
+ //
+
+ fxDevice->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::Configure(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method is called after the device callback object has been initialized
+ and returned to the driver. It would setup the device's queues and their
+ corresponding callback objects.
+
+ Arguments:
+
+ FxDevice - the framework device object for which we're handling events.
+
+ Return Value:
+
+ status
+
+--*/
+{
+ HRESULT hr = S_OK;
+
+ //
+ // Get the bus type GUID for the device and confirm that we're attached to
+ // USB.
+ //
+ // NOTE: Since this device only supports USB we'd normally trust our INF
+ // to ensure this.
+ //
+ // But if the device also supported 1394 then we could
+ // use this to determine which type of bus we were attached to.
+ //
+
+ hr = GetBusTypeGuid();
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ //
+ // Create the read-write queue.
+ //
+
+ hr = CMyReadWriteQueue::CreateInstance(this, &m_ReadWriteQueue);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ //
+ // We use default queue for read/write
+ //
+
+ hr = m_ReadWriteQueue->Configure();
+
+ m_ReadWriteQueue->Release();
+
+ //
+ // Create the control queue and configure forwarding for IOCTL requests.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CMyControlQueue::CreateInstance(this, &m_ControlQueue);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_ControlQueue->Configure();
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice->ConfigureRequestDispatching(
+ m_ControlQueue->GetFxQueue(),
+ WdfRequestDeviceIoControl,
+ true
+ );
+ }
+ m_ControlQueue->Release();
+ }
+ }
+
+ //
+ // Create a manual I/O queue to hold requests for notification when
+ // the switch state changes.
+ //
+
+ hr = m_FxDevice->CreateIoQueue(NULL,
+ FALSE,
+ WdfIoQueueDispatchManual,
+ FALSE,
+ FALSE,
+ &m_SwitchChangeQueue);
+
+
+ //
+ // Release creation reference as object tree will keep a reference
+ //
+
+ m_SwitchChangeQueue->Release();
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_FxDevice->CreateDeviceInterface(&GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL);
+ }
+
+ //
+ // Mark the interface as restricted to allow access to applications bound
+ // using device metadata. Failures here are not fatal so we log them but
+ // ignore them otherwise.
+ //
+ if (SUCCEEDED(hr))
+ {
+ WDF_PROPERTY_STORE_ROOT RootSpecifier;
+ IWDFUnifiedPropertyStoreFactory * pUnifiedPropertyStoreFactory = NULL;
+ IWDFUnifiedPropertyStore * pUnifiedPropertyStore = NULL;
+ DEVPROP_BOOLEAN isRestricted = DEVPROP_TRUE;
+ HRESULT hrSetProp;
+
+ hrSetProp = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pUnifiedPropertyStoreFactory));
+
+ WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrSetProp));
+
+ RootSpecifier.LengthCb = sizeof(RootSpecifier);
+ RootSpecifier.RootClass = WdfPropertyStoreRootClassDeviceInterfaceKey;
+ RootSpecifier.Qualifier.DeviceInterfaceKey.InterfaceGUID = &GUID_DEVINTERFACE_OSRUSBFX2;
+ RootSpecifier.Qualifier.DeviceInterfaceKey.ReferenceString = NULL;
+
+ hrSetProp = pUnifiedPropertyStoreFactory->RetrieveUnifiedDevicePropertyStore(&RootSpecifier,
+ &pUnifiedPropertyStore);
+
+ if (SUCCEEDED(hrSetProp))
+ {
+ hrSetProp = pUnifiedPropertyStore->SetPropertyData(&DEVPKEY_DeviceInterface_Restricted,
+ 0, // Lcid
+ 0, // Flags
+ DEVPROP_TYPE_BOOLEAN,
+ sizeof(isRestricted),
+ &isRestricted);
+ }
+
+ if (FAILED(hrSetProp))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Could not set restricted property %!HRESULT!",
+ hrSetProp
+ );
+ }
+
+ SAFE_RELEASE(pUnifiedPropertyStoreFactory);
+ SAFE_RELEASE(pUnifiedPropertyStore);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to get a pointer to one of the object's callback
+ interfaces.
+
+ Arguments:
+
+ InterfaceId - the interface being requested
+
+ Object - a location to store the interface pointer if successful
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ HRESULT hr;
+
+ if (IsEqualIID(InterfaceId, __uuidof(IPnpCallbackHardware)))
+ {
+ *Object = QueryIPnpCallbackHardware();
+ hr = S_OK;
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IPnpCallback)))
+ {
+ *Object = QueryIPnpCallback();
+ hr = S_OK;
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IPnpCallbackSelfManagedIo)))
+ {
+ *Object = QueryIPnpCallbackSelfManagedIo();
+ hr = S_OK;
+ }
+ else if(IsEqualIID(InterfaceId, __uuidof(IUsbTargetPipeContinuousReaderCallbackReadersFailed)))
+ {
+ *Object = QueryContinousReaderFailureCompletion();
+ hr = S_OK;
+ }
+ else if(IsEqualIID(InterfaceId, __uuidof(IUsbTargetPipeContinuousReaderCallbackReadComplete)))
+ {
+ *Object = QueryContinousReaderCompletion();
+ hr = S_OK;
+ }
+ else
+ {
+ hr = CUnknown::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::OnPrepareHardware(
+ _In_ IWDFDevice * /* FxDevice */
+ )
+/*++
+
+Routine Description:
+
+ This routine is invoked to ready the driver
+ to talk to hardware. It opens the handle to the
+ device and talks to it using the WINUSB interface.
+ It invokes WINUSB to discver the interfaces and stores
+ the information related to bulk endpoints.
+
+Arguments:
+
+ FxDevice : Pointer to the WDF device interface
+
+Return Value:
+
+ HRESULT
+
+--*/
+{
+ PWSTR deviceName = NULL;
+ DWORD deviceNameCch = 0;
+
+ HRESULT hr;
+
+ //
+ // Get the device name.
+ // Get the length to allocate first
+ //
+
+ hr = m_FxDevice->RetrieveDeviceName(NULL, &deviceNameCch);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get device name %!HRESULT!",
+ hr
+ );
+ }
+
+ //
+ // Allocate the buffer
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ deviceName = new WCHAR[deviceNameCch];
+
+ if (deviceName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ //
+ // Get the actual name
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_FxDevice->RetrieveDeviceName(deviceName, &deviceNameCch);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get device name %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Device name %S",
+ deviceName
+ );
+ }
+
+ //
+ // Create USB I/O Targets and configure them
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CreateUsbIoTargets();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ULONG length = sizeof(m_Speed);
+
+ hr = m_pIUsbTargetDevice->RetrieveDeviceInformation(DEVICE_SPEED,
+ &length,
+ &m_Speed);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get usb device speed information %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Speed - %x\n",
+ m_Speed
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ConfigureUsbPipes();
+ }
+
+ // Setup power-management settings on the device.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = SetPowerManagement();
+ }
+
+ //
+ //
+ // Clear the seven segement display to indicate that we're done with
+ // prepare hardware.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IndicateDeviceReady();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ConfigContReaderForInterruptEndPoint();
+ }
+
+ delete[] deviceName;
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::OnReleaseHardware(
+ _In_ IWDFDevice * /* FxDevice */
+ )
+/*++
+
+Routine Description:
+
+ This routine is invoked when the device is being removed or stopped
+ It releases all resources allocated for this device.
+
+Arguments:
+
+ FxDevice - Pointer to the Device object.
+
+Return Value:
+
+ HRESULT - Always succeeds.
+
+--*/
+{
+ //
+ // Delete USB Target Device WDF Object, this will in turn
+ // delete all the children - interface and the pipe objects
+ //
+ // This makes sure that
+ // 1. We drain the the pending read which does not come from an I/O queue
+ // 2. We remove USB target objects from object tree (and thereby free them)
+ // before any potential subsequent OnPrepareHardware creates new ones
+ //
+ // m_pIUsbTargetDevice could be NULL if OnPrepareHardware failed so we need
+ // to guard against that
+ //
+
+ if (m_pIUsbTargetDevice)
+ {
+ m_pIUsbTargetDevice->DeleteWdfObject();
+ }
+
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::CreateUsbIoTargets(
+ )
+/*++
+
+Routine Description:
+
+ This routine creates Usb device, interface and pipe objects
+
+Arguments:
+
+ None
+
+Return Value:
+
+ HRESULT
+--*/
+{
+ HRESULT hr;
+ UCHAR NumEndPoints = 0;
+ IWDFUsbTargetFactory * pIUsbTargetFactory = NULL;
+ IWDFUsbTargetDevice * pIUsbTargetDevice = NULL;
+ IWDFUsbInterface * pIUsbInterface = NULL;
+ IWDFUsbTargetPipe * pIUsbPipe = NULL;
+
+ hr = m_FxDevice->QueryInterface(IID_PPV_ARGS(&pIUsbTargetFactory));
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Cannot get usb target factory %!HRESULT!",
+ hr
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIUsbTargetFactory->CreateUsbTargetDevice(
+ &pIUsbTargetDevice);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to create USB Device I/O Target %!HRESULT!",
+ hr
+ );
+ }
+ else
+ {
+ m_pIUsbTargetDevice = pIUsbTargetDevice;
+
+ //
+ // Release the creation reference as object tree will maintain a reference
+ //
+
+ pIUsbTargetDevice->Release();
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ UCHAR NumInterfaces = pIUsbTargetDevice->GetNumInterfaces();
+
+ WUDF_TEST_DRIVER_ASSERT(1 == NumInterfaces);
+
+ hr = pIUsbTargetDevice->RetrieveUsbInterface(0, &pIUsbInterface);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to retrieve USB interface from USB Device I/O Target %!HRESULT!",
+ hr
+ );
+ }
+ else
+ {
+ m_pIUsbInterface = pIUsbInterface;
+
+ pIUsbInterface->Release(); //release creation reference
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ NumEndPoints = pIUsbInterface->GetNumEndPoints();
+
+ if (NumEndPoints != NUM_OSRUSB_ENDPOINTS) {
+ hr = E_UNEXPECTED;
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Has %d endpoints, expected %d, returning %!HRESULT! ",
+ NumEndPoints,
+ NUM_OSRUSB_ENDPOINTS,
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ for (UCHAR PipeIndex = 0; PipeIndex < NumEndPoints; PipeIndex++)
+ {
+ hr = pIUsbInterface->RetrieveUsbPipeObject(PipeIndex,
+ &pIUsbPipe);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to retrieve USB Pipe for PipeIndex %d, %!HRESULT!",
+ PipeIndex,
+ hr
+ );
+ }
+ else
+ {
+ if ( pIUsbPipe->IsInEndPoint() )
+ {
+ if ( UsbdPipeTypeInterrupt == pIUsbPipe->GetType() )
+ {
+ m_pIUsbInterruptPipe = pIUsbPipe;
+
+ WUDF_TEST_DRIVER_ASSERT (m_pIoTargetInterruptPipeStateMgmt == NULL);
+
+ hr = m_pIUsbInterruptPipe->QueryInterface(__uuidof(
+ IWDFIoTargetStateManagement),
+ reinterpret_cast<void**>(&m_pIoTargetInterruptPipeStateMgmt)
+ );
+ if (FAILED(hr))
+ {
+ m_pIoTargetInterruptPipeStateMgmt = NULL;
+ }
+ }
+ else if ( UsbdPipeTypeBulk == pIUsbPipe->GetType() )
+ {
+ m_pIUsbInputPipe = pIUsbPipe;
+ }
+ else
+ {
+ pIUsbPipe->DeleteWdfObject();
+ }
+ }
+ else if ( pIUsbPipe->IsOutEndPoint() && (UsbdPipeTypeBulk == pIUsbPipe->GetType()) )
+ {
+ m_pIUsbOutputPipe = pIUsbPipe;
+ }
+ else
+ {
+ pIUsbPipe->DeleteWdfObject();
+ }
+
+ SAFE_RELEASE(pIUsbPipe); //release creation reference
+ }
+ }
+
+ if (NULL == m_pIUsbInputPipe || NULL == m_pIUsbOutputPipe)
+ {
+ hr = E_UNEXPECTED;
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Input or output pipe not found, returning %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ SAFE_RELEASE(pIUsbTargetFactory);
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::ConfigureUsbPipes(
+ )
+/*++
+
+Routine Description:
+
+ This routine retrieves the IDs for the bulk end points of the USB device.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ HRESULT
+--*/
+{
+ HRESULT hr = S_OK;
+ LONG timeout;
+
+ //
+ // Set timeout policies for input/output pipes
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ timeout = ENDPOINT_TIMEOUT;
+
+ hr = m_pIUsbInputPipe->SetPipePolicy(PIPE_TRANSFER_TIMEOUT,
+ sizeof(timeout),
+ &timeout);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to set timeout policy for input pipe %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ timeout = ENDPOINT_TIMEOUT;
+
+ hr = m_pIUsbOutputPipe->SetPipePolicy(PIPE_TRANSFER_TIMEOUT,
+ sizeof(timeout),
+ &timeout);
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to set timeout policy for output pipe %!HRESULT!",
+ hr
+ );
+ }
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::IndicateDeviceReady(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method lights the period on the device's seven-segment display to
+ indicate that the driver's PrepareHardware method has completed.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ SEVEN_SEGMENT display = {0};
+
+ HRESULT hr;
+
+ //
+ // First read the contents of the seven segment display.
+ //
+
+ hr = GetSevenSegmentDisplay(&display);
+
+ if (SUCCEEDED(hr))
+ {
+ display.Segments |= 0x08;
+
+ hr = SetSevenSegmentDisplay(&display);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::GetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously retrieves the bar graph display information
+ from the OSR USB-FX2 device. It uses the buffers in the FxRequest
+ to hold the data it retrieves.
+
+ Arguments:
+
+ FxRequest - the request for the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesReturned;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Zero the contents of the buffer - the controller OR's in every
+ // light that's set.
+ //
+
+ BarGraphState->BarsAsUChar = 0;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_BARGRAPH_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) BarGraphState,
+ sizeof(BAR_GRAPH_STATE),
+ &bytesReturned
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::SetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously sets the bar graph display on the OSR USB-FX2
+ device using the buffers in the FxRequest as input.
+
+ Arguments:
+
+ FxRequest - the request to set the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesTransferred;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_SET_BARGRAPH_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) BarGraphState,
+ sizeof(BAR_GRAPH_STATE),
+ &bytesTransferred
+ );
+
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::GetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously retrieves the bar graph display information
+ from the OSR USB-FX2 device. It uses the buffers in the FxRequest
+ to hold the data it retrieves.
+
+ Arguments:
+
+ FxRequest - the request for the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesReturned;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Zero the output buffer - the device will or in the bits for
+ // the lights that are set.
+ //
+
+ SevenSegment->Segments = 0;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_7SEGMENT_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) SevenSegment,
+ sizeof(SEVEN_SEGMENT),
+ &bytesReturned
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::SetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously sets the bar graph display on the OSR USB-FX2
+ device using the buffers in the FxRequest as input.
+
+ Arguments:
+
+ FxRequest - the request to set the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesTransferred;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_SET_7SEGMENT_DISPLAY,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) SevenSegment,
+ sizeof(SEVEN_SEGMENT),
+ &bytesTransferred
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::ReadSwitchState(
+ _In_ PSWITCH_STATE SwitchState
+ )
+/*++
+
+ Routine Description:
+
+ This method synchronously retrieves the bar graph display information
+ from the OSR USB-FX2 device. It uses the buffers in the FxRequest
+ to hold the data it retrieves.
+
+ Arguments:
+
+ FxRequest - the request for the bar-graph info.
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ WINUSB_CONTROL_SETUP_PACKET setupPacket;
+
+ ULONG bytesReturned;
+
+ HRESULT hr = S_OK;
+
+ //
+ // Zero the output buffer - the device will or in the bits for
+ // the lights that are set.
+ //
+
+ SwitchState->SwitchesAsUChar = 0;
+
+ //
+ // Setup the control packet.
+ //
+
+ WINUSB_CONTROL_SETUP_PACKET_INIT( &setupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_SWITCHES,
+ 0,
+ 0 );
+
+ //
+ // Issue the request to WinUsb.
+ //
+
+ hr = SendControlTransferSynchronously(
+ &(setupPacket.WinUsb),
+ (PUCHAR) SwitchState,
+ sizeof(SWITCH_STATE),
+ &bytesReturned
+ );
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::SendControlTransferSynchronously(
+ _In_ PWINUSB_SETUP_PACKET SetupPacket,
+ _Inout_updates_(BufferLength) PBYTE Buffer,
+ _In_ ULONG BufferLength,
+ _Out_ PULONG LengthTransferred
+ )
+{
+ HRESULT hr = S_OK;
+ HRESULT hrRequest = S_OK;
+ IWDFIoRequest *pWdfRequest = NULL;
+ IWDFDriver * FxDriver = NULL;
+ IWDFMemory * FxMemory = NULL;
+ IWDFRequestCompletionParams * FxComplParams = NULL;
+ IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL;
+
+ *LengthTransferred = 0;
+
+ hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface
+ NULL, //pParentObject
+ &pWdfRequest);
+ hrRequest = hr;
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxDevice->GetDriver(&FxDriver);
+
+ hr = FxDriver->CreatePreallocatedWdfMemory( Buffer,
+ BufferLength,
+ NULL, //pCallbackInterface
+ pWdfRequest, //pParetObject
+ &FxMemory );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest,
+ SetupPacket,
+ FxMemory,
+ NULL); //TransferOffset
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pWdfRequest->Send( m_pIUsbTargetDevice,
+ WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
+ 0); //Timeout
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ pWdfRequest->GetCompletionParams(&FxComplParams);
+
+ hr = FxComplParams->GetCompletionStatus();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams));
+ WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI));
+
+ WUDF_TEST_DRIVER_ASSERT( WdfUsbRequestTypeDeviceControlTransfer ==
+ FxUsbComplParams->GetCompletedUsbRequestType() );
+
+ FxUsbComplParams->GetDeviceControlTransferParameters( NULL,
+ LengthTransferred,
+ NULL,
+ NULL );
+ }
+
+ SAFE_RELEASE(FxUsbComplParams);
+ SAFE_RELEASE(FxComplParams);
+ SAFE_RELEASE(FxMemory);
+
+ if (SUCCEEDED(hrRequest))
+ {
+ pWdfRequest->DeleteWdfObject();
+ }
+ SAFE_RELEASE(pWdfRequest);
+
+ SAFE_RELEASE(FxDriver);
+
+ return hr;
+}
+
+WDF_IO_TARGET_STATE
+CMyDevice::GetTargetState(
+ IWDFIoTarget * pTarget
+ )
+{
+ IWDFIoTargetStateManagement * pStateMgmt = NULL;
+ WDF_IO_TARGET_STATE state;
+
+ HRESULT hrQI = pTarget->QueryInterface(IID_PPV_ARGS(&pStateMgmt));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pStateMgmt));
+
+ state = pStateMgmt->GetState();
+
+ SAFE_RELEASE(pStateMgmt);
+
+ return state;
+}
+
+VOID
+CMyDevice::ServiceSwitchChangeQueue(
+ _In_ SWITCH_STATE NewState,
+ _In_ HRESULT CompletionStatus,
+ _In_opt_ IWDFFile *SpecificFile
+ )
+/*++
+
+ Routine Description:
+
+ This method processes switch-state change notification requests as
+ part of reading the OSR device's interrupt pipe. As each read completes
+ this pulls all pending I/O off the switch change queue and completes
+ each request with the current switch state.
+
+ Arguments:
+
+ NewState - the state of the switches
+
+ CompletionStatus - all pending operations are completed with this status.
+
+ SpecificFile - if provided only requests for this file object will get
+ completed.
+
+ Return Value:
+
+ None
+
+--*/
+{
+ IWDFIoRequest *fxRequest;
+
+ HRESULT enumHr = S_OK;
+
+ do
+ {
+ HRESULT hr;
+
+ //
+ // Get the next request.
+ //
+
+ if (NULL != SpecificFile)
+ {
+ enumHr = m_SwitchChangeQueue->RetrieveNextRequestByFileObject(
+ SpecificFile,
+ &fxRequest
+ );
+ }
+ else
+ {
+ enumHr = m_SwitchChangeQueue->RetrieveNextRequest(&fxRequest);
+ }
+
+ //
+ // if we got one then complete it.
+ //
+
+ if (SUCCEEDED(enumHr))
+ {
+ if (SUCCEEDED(CompletionStatus))
+ {
+ IWDFMemory *fxMemory;
+
+ //
+ // First copy the result to the request buffer.
+ //
+
+ fxRequest->GetOutputMemory(&fxMemory );
+
+ hr = fxMemory->CopyFromBuffer(0,
+ &NewState,
+ sizeof(SWITCH_STATE));
+ fxMemory->Release();
+ }
+ else
+ {
+ hr = CompletionStatus;
+ }
+
+ //
+ // Complete the request with the status of the copy (or the completion
+ // status if that was an error).
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ fxRequest->CompleteWithInformation(hr, sizeof(SWITCH_STATE));
+ }
+ else
+ {
+ fxRequest->Complete(hr);
+ }
+
+ fxRequest->Release();
+ }
+ }
+ while (SUCCEEDED(enumHr));
+}
+
+HRESULT
+CMyDevice::SetPowerManagement(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method enables the idle and wake functionality
+ using UMDF. UMDF has been set as the power policy
+ owner (PPO) for the device stack and we are using power
+ managed queues.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ HRESULT hr;
+
+ //
+ // Enable USB selective suspend on the device.
+ //
+
+ hr = m_FxDevice->AssignS0IdleSettings( IdleUsbSelectiveSuspend,
+ PowerDeviceMaximum,
+ IDLE_TIMEOUT_IN_MSEC,
+ IdleAllowUserControl,
+ WdfUseDefault);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to assign S0 idle settings for the device %!HRESULT!",
+ hr
+ );
+ }
+
+ //
+ // Enable Sx wake settings
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = m_FxDevice->AssignSxWakeSettings( PowerDeviceMaximum,
+ WakeAllowUserControl,
+ WdfUseDefault);
+
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Unable to set Sx Wake Settings for the device %!HRESULT!",
+ hr
+ );
+ }
+
+ }
+
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::OnD0Entry(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ UNREFERENCED_PARAMETER(previousState);
+
+ //
+ // Start/Stop the I/O target if you support a continuous reader.
+ // The rest of the I/O is fed through power managed queues. The queue
+ // itself will stop feeding I/O to targets (and will wait for any pending
+ // I/O to complete before going into low power state), hence targets
+ // don�t need to be stopped/started. The continuous reader I/O is outside
+ // of power managed queues so we need to Stop the I/O target on D0Exit and
+ // start it on D0Entry. Please note that bulk pipe target doesn't need to
+ // be stopped/started because I/O submitted to this pipe comes from power
+ // managed I/O queue, which delivers I/O only in power on state.
+ //
+
+ m_pIoTargetInterruptPipeStateMgmt->Start();
+
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnD0Exit(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ UNREFERENCED_PARAMETER(previousState);
+
+ //
+ // Stop the I/O target always succeedes.
+ //
+ m_pIoTargetInterruptPipeStateMgmt->Stop(WdfIoTargetCancelSentIo);
+ return S_OK;
+}
+
+void
+CMyDevice::OnSurpriseRemoval(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return;
+}
+
+HRESULT
+CMyDevice::OnQueryRemove(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnQueryStop(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+//
+// Self Managed Io Callbacks
+//
+
+VOID
+CMyDevice::OnSelfManagedIoCleanup(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return;
+}
+
+VOID
+CMyDevice::OnSelfManagedIoFlush(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+
+ //
+ // Complete every switch change operation with an error.
+ //
+ ServiceSwitchChangeQueue(m_SwitchState,
+ HRESULT_FROM_WIN32(ERROR_DEVICE_REMOVED),
+ NULL);
+
+ return;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoInit(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoRestart(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoStop(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+HRESULT
+CMyDevice::OnSelfManagedIoSuspend(
+ _In_ IWDFDevice* pWdfDevice
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfDevice);
+ return S_OK;
+}
+
+
+
+HRESULT
+CMyDevice::ConfigContReaderForInterruptEndPoint(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine configures a continuous reader on the
+ interrupt endpoint. It's called from the PrepareHarware event.
+
+Arguments:
+
+
+Return Value:
+
+ HRESULT value
+
+--*/
+{
+ HRESULT hr, hrQI;
+ IUsbTargetPipeContinuousReaderCallbackReadComplete *pOnCompletionCallback = NULL;
+ IUsbTargetPipeContinuousReaderCallbackReadersFailed *pOnFailureCallback= NULL;
+ IWDFUsbTargetPipe2 * pIUsbInterruptPipe2;
+
+ hrQI = this->QueryInterface(IID_PPV_ARGS(&pOnCompletionCallback));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pOnCompletionCallback));
+
+ hrQI = this->QueryInterface(IID_PPV_ARGS(&pOnFailureCallback));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pOnFailureCallback));
+
+ hrQI = m_pIUsbInterruptPipe->QueryInterface(IID_PPV_ARGS(&pIUsbInterruptPipe2));
+ WUDF_TEST_DRIVER_ASSERT((SUCCEEDED(hrQI) && pIUsbInterruptPipe2));
+
+ //
+ // Reader requests are not posted to the target automatically.
+ // Driver must explictly call WdfIoTargetStart to kick start the
+ // reader. In this sample, it's done in D0Entry.
+ // By defaut, framework queues two requests to the target
+ // endpoint. Driver can configure up to 10 requests with the
+ // parameter CONCURRENT_READS
+ //
+ hr = pIUsbInterruptPipe2->ConfigureContinuousReader( sizeof(m_SwitchStateBuffer),
+ 0,//header
+ 0,//trailer
+ CONCURRENT_READS,
+ NULL,
+ pOnCompletionCallback,
+ m_pIUsbInterruptPipe,
+ pOnFailureCallback
+ );
+
+ if (FAILED(hr)) {
+ TraceEvents(TRACE_LEVEL_ERROR, TEST_TRACE_DEVICE,
+ "OsrFxConfigContReaderForInterruptEndPoint failed %!HRESULT!",
+ hr);
+ }
+
+ SAFE_RELEASE(pOnCompletionCallback);
+ SAFE_RELEASE(pOnFailureCallback);
+ SAFE_RELEASE(pIUsbInterruptPipe2);
+
+ return hr;
+}
+
+
+BOOL
+CMyDevice::OnReaderFailure(
+ IWDFUsbTargetPipe * pPipe,
+ HRESULT hrCompletion
+ )
+{
+ UNREFERENCED_PARAMETER(pPipe);
+
+ m_InterruptReadProblem = hrCompletion;
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Failure completed with %!HRESULT!",
+ hrCompletion
+ );
+
+ ServiceSwitchChangeQueue(m_SwitchState,
+ hrCompletion,
+ NULL);
+
+ return TRUE;
+}
+
+VOID
+CMyDevice::OnReaderCompletion(
+ IWDFUsbTargetPipe * pPipe,
+ IWDFMemory * pMemory,
+ SIZE_T NumBytesTransferred,
+ PVOID Context
+ )
+{
+ WUDF_TEST_DRIVER_ASSERT(pPipe == (IWDFUsbTargetPipe *)Context);
+
+ //
+ // Make sure that there is data in the read packet. Depending on the device
+ // specification, it is possible for it to return a 0 length read in
+ // certain conditions.
+ //
+
+ if (NumBytesTransferred == 0) {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_DEVICE,
+ "%!FUNC! Zero length read occured on the Interrupt Pipe's "
+ "Continuous Reader\n"
+ );
+ return;
+ }
+
+ WUDF_TEST_DRIVER_ASSERT(NumBytesTransferred == sizeof(m_SwitchState));
+
+ //
+ // Get the switch state
+ //
+
+ PVOID pBuff = pMemory->GetDataBuffer(NULL);
+
+ CopyMemory(&m_SwitchState, pBuff, sizeof(m_SwitchState));
+
+
+ //
+ // Satisfy application request for switch change notification
+ //
+
+ ServiceSwitchChangeQueue(m_SwitchState,
+ S_OK,
+ NULL);
+
+ //
+ // Make sure that the request that got completed is the one that we reuse
+ // Don't Delete the request because it gets reused
+ //
+}
+
+
+HRESULT
+CMyDevice::GetBusTypeGuid(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine gets the device instance ID then invokes SetupDi to
+ retrieve the bus type guid for the device. The bus type guid is
+ stored in object.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ Status
+
+--*/
+{
+ ULONG instanceIdCch = 0;
+ PWSTR instanceId = NULL;
+
+ HDEVINFO deviceInfoSet = NULL;
+ SP_DEVINFO_DATA deviceInfo = {sizeof(SP_DEVINFO_DATA)};
+
+ HRESULT hr;
+
+ //
+ // Retrieve the device instance ID.
+ //
+
+ hr = m_FxDevice->RetrieveDeviceInstanceId(NULL, &instanceIdCch);
+
+ if (FAILED(hr))
+ {
+ goto Exit;
+ }
+
+ instanceId = new WCHAR[instanceIdCch];
+
+ if (instanceId == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ hr = m_FxDevice->RetrieveDeviceInstanceId(instanceId, &instanceIdCch);
+
+ if (FAILED(hr))
+ {
+ goto Exit2;
+ }
+
+ //
+ // Call SetupDI to open the device info.
+ //
+
+ deviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
+
+ if (deviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit2;
+ }
+
+ if (SetupDiOpenDeviceInfo(deviceInfoSet,
+ instanceId,
+ NULL,
+ 0,
+ &deviceInfo) == FALSE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit3;
+ }
+
+ if (SetupDiGetDeviceRegistryProperty(deviceInfoSet,
+ &deviceInfo,
+ SPDRP_BUSTYPEGUID,
+ NULL,
+ (PBYTE) &m_BusTypeGuid,
+ sizeof(m_BusTypeGuid),
+ NULL) == FALSE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto Exit3;
+ }
+
+Exit3:
+ SetupDiDestroyDeviceInfoList(deviceInfoSet);
+
+Exit2:
+
+ delete[] instanceId;
+
+Exit:
+
+ return hr;
+}
+
+HRESULT
+CMyDevice::PlaybackFile(
+ _In_ PFILE_PLAYBACK PlayInfo,
+ _In_ IWDFIoRequest *FxRequest
+ )
+/*++
+
+ Routine Description:
+
+ This method impersonates the caller, opens the file and prints each
+ character to the seven segement display.
+
+ Arguments:
+
+ PlayInfo - the playback info from the request.
+
+ FxRequest - the request (used for impersonation)
+
+ Return Value:
+
+ Status
+
+--*/
+
+{
+ PLAYBACK_IMPERSONATION_CONTEXT context = {PlayInfo, NULL, S_OK};
+ IWDFIoRequest2* fxRequest2;
+
+ HRESULT hr;
+
+ // Convert FxRequest to FxRequest2. No error can occur here.
+ FxRequest->QueryInterface(IID_PPV_ARGS(&fxRequest2));
+ _Analysis_assume_(fxRequest2 != NULL);
+
+ //
+ // Impersonate and open the playback file.
+ //
+
+ hr = FxRequest->Impersonate(
+ SecurityImpersonation,
+ this->QueryIImpersonateCallback(),
+ &context
+ );
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ //
+ // Release the reference that was added in QueryIImpersonateCallback()
+ //
+ this->Release();
+
+ hr = context.Hr;
+
+ if (FAILED(hr))
+ {
+ goto exit;
+ }
+
+ //
+ // The impersonation callback succeeded - tell code analysis that the
+ // file handle is non-null
+ //
+
+ _Analysis_assume_(context.FileHandle != NULL);
+
+ //
+ // Read from the file one character at a time until we hit
+ // EOF or the request is cancelled.
+ //
+
+ do
+ {
+ UCHAR c;
+ ULONG bytesRead;
+
+ //
+ // Check for cancellation.
+ //
+
+ if (fxRequest2->IsCanceled())
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
+ }
+ else
+ {
+ BOOL result;
+
+ //
+ // Read a character from the file and see if we can
+ // encode it on the display.
+ //
+
+ result = ReadFile(context.FileHandle,
+ &c,
+ sizeof(c),
+ &bytesRead,
+ NULL);
+
+ if (result)
+ {
+ SEVEN_SEGMENT segment;
+ BAR_GRAPH_STATE barGraph;
+
+ if (bytesRead > 0)
+ {
+ #pragma prefast(suppress:__WARNING_USING_UNINIT_VAR,"Above this->Release() method does not actually free 'this'")
+ if(EncodeSegmentValue(c, &segment) == true)
+ {
+ barGraph.BarsAsUChar = c;
+
+ SetSevenSegmentDisplay(&segment);
+ SetBarGraphDisplay(&barGraph);
+ }
+
+ Sleep(PlayInfo->Delay);
+ }
+ else
+ {
+ hr = S_OK;
+ break;
+ }
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ } while(SUCCEEDED(hr));
+
+ CloseHandle(context.FileHandle);
+
+exit:
+
+ fxRequest2->Release();
+ return hr;
+}
+
+VOID
+CMyDevice::OnImpersonate(
+ _In_ PVOID Context
+ )
+/*++
+
+ Routine Description:
+
+ This routine handles the impersonation for the PLAY FILE I/O control.
+
+ Arguments:
+
+ Context - pointer to the impersonation context
+
+ Return Value:
+
+ None
+
+--*/
+{
+ PPLAYBACK_IMPERSONATION_CONTEXT context;
+
+ context = (PPLAYBACK_IMPERSONATION_CONTEXT) Context;
+
+ context->FileHandle = CreateFile(context->PlaybackInfo->Path,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if (context->FileHandle == INVALID_HANDLE_VALUE)
+ {
+ DWORD error = GetLastError();
+ context->Hr = HRESULT_FROM_WIN32(error);
+ }
+ else
+ {
+ context->Hr = S_OK;
+ }
+
+ return;
+}
+
+#define SS_LEFT (SS_TOP_LEFT | SS_BOTTOM_LEFT)
+#define SS_RIGHT (SS_TOP_RIGHT | SS_BOTTOM_RIGHT)
+
+bool
+CMyDevice::EncodeSegmentValue(
+ _In_ UCHAR Character,
+ _Out_ SEVEN_SEGMENT *SevenSegment
+ )
+{
+ UCHAR letterMap[] = {
+ (SS_TOP | SS_BOTTOM_LEFT | SS_RIGHT | SS_CENTER | SS_BOTTOM), // a
+ (SS_LEFT | SS_CENTER | SS_BOTTOM | SS_BOTTOM_RIGHT), // b
+ (SS_CENTER | SS_BOTTOM_LEFT | SS_BOTTOM), // c
+ (SS_BOTTOM_LEFT | SS_CENTER | SS_BOTTOM | SS_RIGHT), // d
+ (SS_LEFT | SS_TOP | SS_CENTER | SS_BOTTOM), // e
+ (SS_LEFT | SS_TOP | SS_CENTER), // f
+ (SS_TOP | SS_TOP_LEFT | SS_CENTER | SS_BOTTOM | SS_RIGHT), // g
+ (SS_LEFT | SS_RIGHT | SS_CENTER), // h
+ (SS_BOTTOM_LEFT), // i
+ (SS_BOTTOM | SS_RIGHT), // j
+ (SS_LEFT | SS_CENTER | SS_BOTTOM), // k
+ (SS_LEFT | SS_BOTTOM), // l
+ (SS_LEFT | SS_TOP | SS_RIGHT), // m
+ (SS_BOTTOM_LEFT | SS_CENTER | SS_BOTTOM_RIGHT), // n
+ (SS_BOTTOM_LEFT | SS_BOTTOM_RIGHT | SS_CENTER | SS_BOTTOM), // o
+ (SS_LEFT | SS_TOP | SS_CENTER | SS_TOP_RIGHT), // p
+ (SS_TOP_LEFT | SS_TOP | SS_CENTER | SS_RIGHT), // q
+ (SS_BOTTOM_LEFT | SS_CENTER), // r
+ (SS_TOP_LEFT |
+ SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_BOTTOM_RIGHT), // s
+ (SS_TOP | SS_RIGHT), // t
+ (SS_LEFT | SS_RIGHT | SS_BOTTOM), // u
+ (SS_BOTTOM_LEFT | SS_BOTTOM | SS_BOTTOM_RIGHT), // v
+ (SS_LEFT | SS_BOTTOM | SS_BOTTOM_RIGHT), // w
+ (SS_LEFT | SS_CENTER | SS_RIGHT), // x
+ (SS_TOP_LEFT | SS_CENTER | SS_RIGHT), // y
+ (SS_TOP_RIGHT |
+ SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_BOTTOM_LEFT), // z
+ };
+
+ UCHAR numberMap[] = {
+ (SS_LEFT | SS_TOP | SS_BOTTOM | SS_RIGHT | SS_DOT), // 0
+ (SS_RIGHT | SS_DOT), // 1
+ (SS_TOP |
+ SS_TOP_RIGHT | SS_CENTER | SS_BOTTOM_LEFT |
+ SS_BOTTOM | SS_DOT), // 2
+ (SS_TOP | SS_CENTER | SS_BOTTOM | SS_RIGHT | SS_DOT), // 3
+ (SS_TOP_LEFT | SS_CENTER | SS_RIGHT | SS_DOT), // 4
+ (SS_TOP_LEFT |
+ SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_BOTTOM_RIGHT | SS_DOT), // 5
+ (SS_TOP | SS_CENTER | SS_BOTTOM |
+ SS_LEFT | SS_BOTTOM_RIGHT | SS_DOT), // 6
+ (SS_TOP | SS_RIGHT | SS_DOT), // 7
+ (SS_TOP | SS_BOTTOM | SS_CENTER |
+ SS_LEFT | SS_RIGHT | SS_DOT), // 8
+ (SS_TOP_LEFT | SS_TOP | SS_CENTER | SS_RIGHT | SS_DOT), // 9
+ };
+
+ if (((Character >= 'a') && (Character <= 'z')) ||
+ ((Character >= 'A') && (Character <= 'Z')))
+ {
+ SevenSegment->Segments = letterMap[tolower(Character) - 'a'];
+ return true;
+ }
+ else if ((Character >= '0') && (Character <= '9'))
+ {
+ SevenSegment->Segments = numberMap[Character - '0'];
+ return true;
+ }
+ else
+ {
+ SevenSegment->Segments = 0;
+ return false;
+ }
+}
+
diff --git a/usb/umdf_fx2/driver/Device.h b/usb/umdf_fx2/driver/Device.h
new file mode 100644
index 00000000..641a04de
--- /dev/null
+++ b/usb/umdf_fx2/driver/Device.h
@@ -0,0 +1,604 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Device.h
+
+Abstract:
+
+ This module contains the type definitions for the UMDF OSR Fx2 sample
+ driver's device callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+#include "internal.h"
+
+#define ENDPOINT_TIMEOUT 10000
+#define NUM_OSRUSB_ENDPOINTS 3
+
+//
+// Define the vendor commands supported by our device
+//
+#define USBFX2LK_READ_7SEGMENT_DISPLAY 0xD4
+#define USBFX2LK_READ_SWITCHES 0xD6
+#define USBFX2LK_READ_BARGRAPH_DISPLAY 0xD7
+#define USBFX2LK_SET_BARGRAPH_DISPLAY 0xD8
+#define USBFX2LK_IS_HIGH_SPEED 0xD9
+#define USBFX2LK_REENUMERATE 0xDA
+#define USBFX2LK_SET_7SEGMENT_DISPLAY 0xDB
+
+typedef struct {
+ UCHAR Segments;
+} SEVEN_SEGMENT, *PSEVEN_SEGMENT;
+
+//
+// Context for the impersonation callback.
+//
+
+typedef struct
+{
+ PFILE_PLAYBACK PlaybackInfo;
+
+ HANDLE FileHandle;
+
+ HRESULT Hr;
+} PLAYBACK_IMPERSONATION_CONTEXT, *PPLAYBACK_IMPERSONATION_CONTEXT;
+
+//
+// Class for the driver.
+//
+
+class CMyDevice :
+ public CUnknown,
+ public IPnpCallbackHardware,
+ public IPnpCallback,
+ public IPnpCallbackSelfManagedIo,
+ public IUsbTargetPipeContinuousReaderCallbackReadersFailed,
+ public IUsbTargetPipeContinuousReaderCallbackReadComplete,
+ public IImpersonateCallback
+{
+//
+// Private data members.
+//
+private:
+ //
+ // Weak reference to framework device
+ // Use IWDFDevice2 so we can set power policy settings
+ //
+ IWDFDevice2 *m_FxDevice;
+
+ //
+ // Weak reference to the control queue
+ //
+ PCMyReadWriteQueue m_ReadWriteQueue;
+
+ //
+ // Weak reference to the control queue
+ //
+ PCMyControlQueue m_ControlQueue;
+
+ //
+ // The bus type for this device (used here for
+ // illustrative purposes only)
+ //
+
+ GUID m_BusTypeGuid;
+
+ //
+ // USB Device I/O Target
+ //
+ IWDFUsbTargetDevice * m_pIUsbTargetDevice;
+
+ //
+ // USB Interface
+ //
+ IWDFUsbInterface * m_pIUsbInterface;
+
+ //
+ // USB Input pipe for Reads
+ //
+ IWDFUsbTargetPipe * m_pIUsbInputPipe;
+
+ //
+ // USB Output pipe for writes
+ //
+ IWDFUsbTargetPipe * m_pIUsbOutputPipe;
+
+ //
+ // USB interrupt pipe
+ //
+ IWDFUsbTargetPipe * m_pIUsbInterruptPipe;
+
+ //
+ // Use I/O target state management interfaces if you are going to
+ // support a continuous reader.
+ //
+
+ //
+ // USB interrupt pipe state management
+ //
+ IWDFIoTargetStateManagement * m_pIoTargetInterruptPipeStateMgmt;
+
+ //
+ // Device Speed (Low, Full, High)
+ //
+ UCHAR m_Speed;
+
+ //
+ // Current switch state
+ //
+ SWITCH_STATE m_SwitchState;
+
+ //
+ // Request to be used for pending reads from interrupt pipe
+ // (to get switch state change notifications)
+ //
+
+ IWDFIoRequest * m_RequestForPendingRead;
+
+ //
+ // If reads stopped because of a transient problem, the error status
+ // is stored here.
+ //
+
+ HRESULT m_InterruptReadProblem;
+
+ //
+ // Switch state buffer - this might hold the transient value
+ // m_SwitchState holds stable value of the switch state
+ //
+ SWITCH_STATE m_SwitchStateBuffer;
+
+ //
+ // A manual queue to hold requests for changes in the I/O switch state.
+ //
+
+ IWDFIoQueue * m_SwitchChangeQueue;
+
+//
+// Private methods.
+//
+
+private:
+
+ CMyDevice(
+ VOID
+ ) :
+ m_FxDevice(NULL),
+ m_ControlQueue(NULL),
+ m_ReadWriteQueue(NULL),
+ m_SwitchChangeQueue(NULL),
+ m_pIUsbTargetDevice(NULL),
+ m_pIUsbInterface(NULL),
+ m_pIUsbInputPipe(NULL),
+ m_pIUsbOutputPipe(NULL),
+ m_pIUsbInterruptPipe(NULL),
+ m_Speed(0),
+ m_InterruptReadProblem(S_OK),
+ m_RequestForPendingRead(NULL),
+ m_pIoTargetInterruptPipeStateMgmt(NULL)
+ {
+ ZeroMemory(&m_BusTypeGuid, sizeof(m_BusTypeGuid));
+ }
+
+ ~CMyDevice(
+ );
+
+ HRESULT
+ Initialize(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ );
+
+ //
+ // Helper methods
+ //
+
+ HRESULT
+ GetBusTypeGuid(
+ VOID
+ );
+
+ HRESULT
+ CreateUsbIoTargets(
+ VOID
+ );
+
+
+ HRESULT
+ ConfigureUsbPipes(
+ );
+
+ HRESULT
+ SetPowerManagement(
+ VOID
+ );
+
+ HRESULT
+ IndicateDeviceReady(
+ VOID
+ );
+
+ //
+ // Helper functions
+ //
+
+ HRESULT
+ SendControlTransferSynchronously(
+ _In_ PWINUSB_SETUP_PACKET SetupPacket,
+ _Inout_updates_(BufferLength) PBYTE Buffer,
+ _In_ ULONG BufferLength,
+ _Out_ PULONG LengthTransferred
+ );
+
+ static
+ WDF_IO_TARGET_STATE
+ GetTargetState(
+ IWDFIoTarget * pTarget
+ );
+
+ VOID
+ ServiceSwitchChangeQueue(
+ _In_ SWITCH_STATE NewState,
+ _In_ HRESULT CompletionStatus,
+ _In_opt_ IWDFFile *SpecificFile
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this driver.
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ IWDFDriver *FxDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit,
+ _Out_ PCMyDevice *Device
+ );
+
+ IWDFDevice *
+ GetFxDevice(
+ VOID
+ )
+ {
+ return m_FxDevice;
+ }
+
+ HRESULT
+ Configure(
+ VOID
+ );
+
+ IPnpCallback *
+ QueryIPnpCallback(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IPnpCallback *>(this);
+ }
+
+ IPnpCallbackHardware *
+ QueryIPnpCallbackHardware(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IPnpCallbackHardware *>(this);
+ }
+
+ IPnpCallbackSelfManagedIo *
+ QueryIPnpCallbackSelfManagedIo(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IPnpCallbackSelfManagedIo *>(this);
+ }
+
+
+ IUsbTargetPipeContinuousReaderCallbackReadersFailed *
+ QueryContinousReaderFailureCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IUsbTargetPipeContinuousReaderCallbackReadersFailed *>(this);
+ }
+
+ IUsbTargetPipeContinuousReaderCallbackReadComplete *
+ QueryContinousReaderCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IUsbTargetPipeContinuousReaderCallbackReadComplete *>(this);
+ }
+
+ IImpersonateCallback *
+ QueryIImpersonateCallback(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IImpersonateCallback *>(this);
+ }
+
+ HRESULT
+ GetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ );
+
+ HRESULT
+ SetBarGraphDisplay(
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ );
+
+ HRESULT
+ GetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ );
+
+ HRESULT
+ SetSevenSegmentDisplay(
+ _In_ PSEVEN_SEGMENT SevenSegment
+ );
+
+ HRESULT
+ ReadSwitchState(
+ _In_ PSWITCH_STATE SwitchState
+ );
+
+ bool
+ EncodeSegmentValue(
+ _In_ UCHAR Character,
+ _Out_ SEVEN_SEGMENT *SevenSegment
+ );
+
+ HRESULT
+ PlaybackFile(
+ _In_ PFILE_PLAYBACK PlaybackInfo,
+ _In_ IWDFIoRequest *FxRequest
+ );
+
+ //
+ //returns a weak reference to the target USB device
+ //DO NOT release it
+ //
+ IWDFUsbTargetDevice *
+ GetUsbTargetDevice(
+ )
+ {
+ return m_pIUsbTargetDevice;
+ }
+
+ //
+ //returns a weak reference to input pipe
+ //DO NOT release it
+ //
+ IWDFUsbTargetPipe *
+ GetInputPipe(
+ )
+ {
+ return m_pIUsbInputPipe;
+ }
+
+ //
+ //returns a weak reference to output pipe
+ //DO NOT release it
+ //
+ IWDFUsbTargetPipe *
+ GetOutputPipe(
+ )
+ {
+ return m_pIUsbOutputPipe;
+ }
+
+ IWDFIoQueue *
+ GetSwitchChangeQueue(
+ VOID
+ )
+ {
+ return m_SwitchChangeQueue;
+ }
+
+ PSWITCH_STATE
+ GetCurrentSwitchState(
+ VOID
+ )
+ {
+ return &m_SwitchState;
+ }
+
+
+ HRESULT
+ ConfigContReaderForInterruptEndPoint(
+ VOID
+ );
+//
+// COM methods
+//
+public:
+
+ //
+ // IUnknown methods.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+
+ //
+ // IPnpCallbackHardware
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnPrepareHardware(
+ _In_ IWDFDevice *FxDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnReleaseHardware(
+ _In_ IWDFDevice *FxDevice
+ );
+
+
+ //
+ // IPnpCallback
+ //
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnD0Entry(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnD0Exit(
+ _In_ IWDFDevice* pWdfDevice,
+ _In_ WDF_POWER_DEVICE_STATE previousState
+ );
+
+ virtual
+ void
+ STDMETHODCALLTYPE
+ OnSurpriseRemoval(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnQueryRemove(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnQueryStop(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ //
+ // IPnpCallbackSelfManagedIo
+ //
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnSelfManagedIoCleanup(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnSelfManagedIoFlush(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoInit(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoRestart(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoStop(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnSelfManagedIoSuspend(
+ _In_ IWDFDevice* pWdfDevice
+ );
+
+ //
+ // IUsbTargetPipeContinuousReaderCallbackReadersFailed
+ //
+ virtual
+ BOOL
+ STDMETHODCALLTYPE
+ OnReaderFailure(
+ IWDFUsbTargetPipe * pPipe,
+ HRESULT hrCompletion
+ );
+
+ //
+ // IUsbTargetPipeContinuousReaderCallbackReadComplete
+ //
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnReaderCompletion(
+ IWDFUsbTargetPipe * pPipe,
+ IWDFMemory * pMemory,
+ SIZE_T NumBytesTransferred,
+ PVOID Context
+ );
+
+ // IImpersonateCallback
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnImpersonate(
+ _In_ PVOID Context
+ );
+};
+
diff --git a/usb/umdf_fx2/driver/Driver.cpp b/usb/umdf_fx2/driver/Driver.cpp
new file mode 100644
index 00000000..d6635242
--- /dev/null
+++ b/usb/umdf_fx2/driver/Driver.cpp
@@ -0,0 +1,220 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ Driver.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR Fx2 driver's
+ core driver callback object.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "driver.tmh"
+
+HRESULT
+CMyDriver::CreateInstance(
+ _Out_ PCMyDriver *Driver
+ )
+/*++
+
+ Routine Description:
+
+ This static method is invoked in order to create and initialize a new
+ instance of the driver class. The caller should arrange for the object
+ to be released when it is no longer in use.
+
+ Arguments:
+
+ Driver - a location to store a referenced pointer to the new instance
+
+ Return Value:
+
+ S_OK if successful, or error otherwise.
+
+--*/
+{
+ PCMyDriver driver;
+ HRESULT hr;
+
+ //
+ // Allocate the callback object.
+ //
+
+ driver = new CMyDriver();
+
+ if (NULL == driver)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Initialize the callback object.
+ //
+
+ hr = driver->Initialize();
+
+ if (SUCCEEDED(hr))
+ {
+ //
+ // Store a pointer to the new, initialized object in the output
+ // parameter.
+ //
+
+ *Driver = driver;
+ }
+ else
+ {
+
+ //
+ // Release the reference on the driver object to get it to delete
+ // itself.
+ //
+
+ driver->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyDriver::Initialize(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method is called to initialize a newly created driver callback object
+ before it is returned to the creator. Unlike the constructor, the
+ Initialize method contains operations which could potentially fail.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ return S_OK;
+}
+
+HRESULT
+CMyDriver::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Interface
+ )
+/*++
+
+ Routine Description:
+
+ This method returns a pointer to the requested interface on the callback
+ object..
+
+ Arguments:
+
+ InterfaceId - the IID of the interface to query/reference
+
+ Interface - a location to store the interface pointer.
+
+ Return Value:
+
+ S_OK if the interface is supported.
+ E_NOINTERFACE if it is not supported.
+
+--*/
+{
+ if (IsEqualIID(InterfaceId, __uuidof(IDriverEntry)))
+ {
+ *Interface = QueryIDriverEntry();
+ return S_OK;
+ }
+ else
+ {
+ return CUnknown::QueryInterface(InterfaceId, Interface);
+ }
+}
+
+HRESULT
+CMyDriver::OnDeviceAdd(
+ _In_ IWDFDriver *FxWdfDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ )
+/*++
+
+ Routine Description:
+
+ The FX invokes this method when it wants to install our driver on a device
+ stack. This method creates a device callback object, then calls the Fx
+ to create an Fx device object and associate the new callback object with
+ it.
+
+ Arguments:
+
+ FxWdfDriver - the Fx driver object.
+
+ FxDeviceInit - the initialization information for the device.
+
+ Return Value:
+
+ status
+
+--*/
+{
+ HRESULT hr;
+
+ PCMyDevice device = NULL;
+
+ //
+ // TODO: Do any per-device initialization (reading settings from the
+ // registry for example) that's necessary before creating your
+ // device callback object here. Otherwise you can leave such
+ // initialization to the initialization of the device event
+ // handler.
+ //
+
+ //
+ // Create a new instance of our device callback object
+ //
+
+ hr = CMyDevice::CreateInstance(FxWdfDriver, FxDeviceInit, &device);
+
+ //
+ // TODO: Change any per-device settings that the object exposes before
+ // calling Configure to let it complete its initialization.
+ //
+
+ //
+ // If that succeeded then call the device's construct method. This
+ // allows the device to create any queues or other structures that it
+ // needs now that the corresponding fx device object has been created.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = device->Configure();
+ }
+
+ //
+ // Release the reference on the device callback object now that it's been
+ // associated with an fx device object.
+ //
+
+ if (NULL != device)
+ {
+ device->Release();
+ }
+
+ return hr;
+}
diff --git a/usb/umdf_fx2/driver/Driver.h b/usb/umdf_fx2/driver/Driver.h
new file mode 100644
index 00000000..d9cafb4e
--- /dev/null
+++ b/usb/umdf_fx2/driver/Driver.h
@@ -0,0 +1,149 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Driver.h
+
+Abstract:
+
+ This module contains the type definitions for the UMDF OSR Fx2 sample's
+ driver callback class.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// This class handles driver events for the OSR Fx2 sample. In particular
+// it supports the OnDeviceAdd event, which occurs when the driver is called
+// to setup per-device handlers for a new device stack.
+//
+
+class CMyDriver : public CUnknown, public IDriverEntry
+{
+//
+// Private data members.
+//
+private:
+
+//
+// Private methods.
+//
+private:
+
+ //
+ // Returns a refernced pointer to the IDriverEntry interface.
+ //
+
+ IDriverEntry *
+ QueryIDriverEntry(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IDriverEntry*>(this);
+ }
+
+ HRESULT
+ Initialize(
+ VOID
+ );
+
+//
+// Public methods
+//
+public:
+
+ //
+ // The factory method used to create an instance of this driver.
+ //
+
+ static
+ HRESULT
+ CreateInstance(
+ _Out_ PCMyDriver *Driver
+ );
+
+//
+// COM methods
+//
+public:
+
+ //
+ // IDriverEntry methods
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnInitialize(
+ _In_ IWDFDriver *FxWdfDriver
+ )
+ {
+ UNREFERENCED_PARAMETER(FxWdfDriver);
+
+ return S_OK;
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ OnDeviceAdd(
+ _In_ IWDFDriver *FxWdfDriver,
+ _In_ IWDFDeviceInitialize *FxDeviceInit
+ );
+
+ virtual
+ VOID
+ STDMETHODCALLTYPE
+ OnDeinitialize(
+ _In_ IWDFDriver *FxWdfDriver
+ )
+ {
+ UNREFERENCED_PARAMETER(FxWdfDriver);
+
+ return;
+ }
+
+ //
+ // IUnknown methods.
+ //
+ // We have to implement basic ones here that redirect to the
+ // base class becuase of the multiple inheritance.
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+};
diff --git a/usb/umdf_fx2/driver/OsrUsbFx2.ctl b/usb/umdf_fx2/driver/OsrUsbFx2.ctl
new file mode 100644
index 00000000..4dab56ae
--- /dev/null
+++ b/usb/umdf_fx2/driver/OsrUsbFx2.ctl
@@ -0,0 +1 @@
+da5fbdfd-1eae-4ecf-b426-a3818f325ddb WudfOsrUsbFx2TraceGuid
diff --git a/usb/umdf_fx2/driver/OsrUsbFx2.rc b/usb/umdf_fx2/driver/OsrUsbFx2.rc
new file mode 100644
index 00000000..36f10ea9
--- /dev/null
+++ b/usb/umdf_fx2/driver/OsrUsbFx2.rc
@@ -0,0 +1,21 @@
+//---------------------------------------------------------------------------
+// OsrUsbDevice.rc
+//
+// Copyright (c) Microsoft Corporation, All Rights Reserved
+//---------------------------------------------------------------------------
+
+
+#include <windows.h>
+#include <ntverp.h>
+
+//
+// TODO: Change the file description and file names to match your binary.
+//
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "WDF:UMDF OSR USB Fx2 User-Mode Driver Sample"
+#define VER_INTERNALNAME_STR "WUDFOsrUsbFx2"
+#define VER_ORIGINALFILENAME_STR "WUDFOsrUsbFx2.dll"
+
+#include "common.ver"
diff --git a/usb/umdf_fx2/driver/ReadWriteQueue.cpp b/usb/umdf_fx2/driver/ReadWriteQueue.cpp
new file mode 100644
index 00000000..46144829
--- /dev/null
+++ b/usb/umdf_fx2/driver/ReadWriteQueue.cpp
@@ -0,0 +1,425 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs
+ the read/write/ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "ReadWriteQueue.tmh"
+
+VOID
+CMyReadWriteQueue::OnCompletion(
+ _In_ IWDFIoRequest* pWdfRequest,
+ _In_ IWDFIoTarget* pIoTarget,
+ _In_ IWDFRequestCompletionParams* pParams,
+ _In_ PVOID pContext
+ )
+{
+ UNREFERENCED_PARAMETER(pIoTarget);
+ UNREFERENCED_PARAMETER(pContext);
+
+ pWdfRequest->CompleteWithInformation(
+ pParams->GetCompletionStatus(),
+ pParams->GetInformation()
+ );
+}
+
+void
+CMyReadWriteQueue::ForwardFormattedRequest(
+ _In_ IWDFIoRequest* pRequest,
+ _In_ IWDFIoTarget* pIoTarget
+ )
+{
+ //
+ //First set the completion callback
+ //
+
+ IRequestCallbackRequestCompletion * pCompletionCallback = NULL;
+ HRESULT hrQI = this->QueryInterface(IID_PPV_ARGS(&pCompletionCallback));
+ WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI) && (NULL != pCompletionCallback));
+
+ pRequest->SetCompletionCallback(
+ pCompletionCallback,
+ NULL
+ );
+
+ pCompletionCallback->Release();
+ pCompletionCallback = NULL;
+
+ //
+ //Send down the request
+ //
+
+ HRESULT hrSend = S_OK;
+ hrSend = pRequest->Send(pIoTarget,
+ 0, //flags
+ 0); //timeout
+
+ if (FAILED(hrSend))
+ {
+ pRequest->CompleteWithInformation(hrSend, 0);
+ }
+
+ return;
+}
+
+
+CMyReadWriteQueue::CMyReadWriteQueue(
+ _In_ PCMyDevice Device
+ ) :
+ CMyQueue(Device)
+{
+}
+
+//
+// Queue destructor.
+// Free up the buffer, wait for thread to terminate and
+//
+
+CMyReadWriteQueue::~CMyReadWriteQueue(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+ IUnknown implementation of Release
+
+Aruments:
+
+
+Return Value:
+
+ ULONG (reference count after Release)
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC! Entry"
+ );
+
+}
+
+
+HRESULT
+STDMETHODCALLTYPE
+CMyReadWriteQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+Routine Description:
+
+
+ Query Interface
+
+Aruments:
+
+ Follows COM specifications
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ HRESULT hr;
+
+
+ if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackWrite)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackWrite();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackRead)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackRead();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IRequestCallbackRequestCompletion)))
+ {
+ hr = S_OK;
+ *Object = QueryIRequestCallbackRequestCompletion();
+ }
+ else if (IsEqualIID(InterfaceId, __uuidof(IQueueCallbackIoStop)))
+ {
+ hr = S_OK;
+ *Object = QueryIQueueCallbackIoStop();
+ }
+ else
+ {
+ hr = CMyQueue::QueryInterface(InterfaceId, Object);
+ }
+
+ return hr;
+}
+
+//
+// Initialize
+//
+
+HRESULT
+CMyReadWriteQueue::CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyReadWriteQueue *Queue
+ )
+/*++
+
+Routine Description:
+
+
+ CreateInstance creates an instance of the queue object.
+
+Aruments:
+
+ ppUkwn - OUT parameter is an IUnknown interface to the queue object
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ PCMyReadWriteQueue queue;
+ HRESULT hr = S_OK;
+
+ queue = new CMyReadWriteQueue(Device);
+
+ if (NULL == queue)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Call the queue callback object to initialize itself. This will create
+ // its partner queue framework object.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = queue->Initialize();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *Queue = queue;
+ }
+ else
+ {
+ SAFE_RELEASE(queue);
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyReadWriteQueue::Initialize(
+ )
+{
+ HRESULT hr;
+
+ //
+ // First initialize the base class. This will create the partner FxIoQueue
+ // object and setup automatic forwarding of I/O controls.
+ //
+
+ hr = __super::Initialize(WdfIoQueueDispatchParallel,
+ true,
+ true);
+
+ //
+ // return the status.
+ //
+
+ return hr;
+}
+
+STDMETHODIMP_ (void)
+CMyReadWriteQueue::OnWrite(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T BytesToWrite
+ )
+/*++
+
+Routine Description:
+
+
+ Write dispatch routine
+ IQueueCallbackWrite
+
+Aruments:
+
+ pWdfQueue - Framework Queue instance
+ pWdfRequest - Framework Request instance
+ BytesToWrite - Lenth of bytes in the write buffer
+
+ Allocate and copy data to local buffer
+Return Value:
+
+ VOID
+
+--*/
+{
+ UNREFERENCED_PARAMETER(pWdfQueue);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n",
+ this,
+ pWdfRequest,
+ (ULONG)(ULONG_PTR)BytesToWrite
+ );
+
+ HRESULT hr = S_OK;
+ IWDFMemory * pInputMemory = NULL;
+ IWDFUsbTargetPipe * pOutputPipe = m_Device->GetOutputPipe();
+
+ pWdfRequest->GetInputMemory(&pInputMemory);
+
+ hr = pOutputPipe->FormatRequestForWrite(
+ pWdfRequest,
+ NULL, //pFile
+ pInputMemory,
+ NULL, //Memory offset
+ NULL //DeviceOffset
+ );
+
+ if (FAILED(hr))
+ {
+ pWdfRequest->Complete(hr);
+ }
+ else
+ {
+ ForwardFormattedRequest(pWdfRequest, pOutputPipe);
+ }
+
+ SAFE_RELEASE(pInputMemory);
+
+ return;
+}
+
+STDMETHODIMP_ (void)
+CMyReadWriteQueue::OnRead(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T BytesToRead
+ )
+/*++
+
+Routine Description:
+
+
+ Read dispatch routine
+ IQueueCallbackRead
+
+Aruments:
+
+ pWdfQueue - Framework Queue instance
+ pWdfRequest - Framework Request instance
+ BytesToRead - Lenth of bytes in the read buffer
+
+ Copy available data into the read buffer
+Return Value:
+
+ VOID
+
+--*/
+{
+ UNREFERENCED_PARAMETER(pWdfQueue);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC!: Queue %p Request %p BytesToTransfer %d\n",
+ this,
+ pWdfRequest,
+ (ULONG)(ULONG_PTR)BytesToRead
+ );
+
+ HRESULT hr = S_OK;
+ IWDFMemory * pOutputMemory = NULL;
+
+ pWdfRequest->GetOutputMemory(&pOutputMemory);
+
+ hr = m_Device->GetInputPipe()->FormatRequestForRead(
+ pWdfRequest,
+ NULL, //pFile
+ pOutputMemory,
+ NULL, //Memory offset
+ NULL //DeviceOffset
+ );
+
+ if (FAILED(hr))
+ {
+ pWdfRequest->Complete(hr);
+ }
+ else
+ {
+ ForwardFormattedRequest(pWdfRequest, m_Device->GetInputPipe());
+ }
+
+ SAFE_RELEASE(pOutputMemory);
+
+ return;
+}
+
+STDMETHODIMP_ (void)
+CMyReadWriteQueue::OnIoStop(
+ _In_ IWDFIoQueue * pWdfQueue,
+ _In_ IWDFIoRequest * pWdfRequest,
+ _In_ ULONG ActionFlags
+ )
+{
+ UNREFERENCED_PARAMETER(pWdfQueue);
+
+
+ //
+ // The driver owns the request and no locking constraint is safe for
+ // the queue callbacks
+ //
+ if (ActionFlags == WdfRequestStopActionSuspend )
+ {
+ IWDFIoRequest2 * request2 = NULL;
+ HRESULT hr;
+
+ hr = pWdfRequest->QueryInterface(IID_PPV_ARGS(&request2));
+ if (FAILED(hr))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC!: Failed to QI for IWDFIoRequest2: %!hresult!",
+ hr);
+ return;
+ }
+
+ request2->StopAcknowledge(FALSE); //don't requeue
+ SAFE_RELEASE(request2);
+ }
+ else if(ActionFlags == WdfRequestStopActionPurge)
+ {
+ //
+ // Cancel the sent request since we are asked to purge the request
+ //
+
+ pWdfRequest->CancelSentRequest();
+ }
+
+ return;
+}
+
diff --git a/usb/umdf_fx2/driver/ReadWriteQueue.h b/usb/umdf_fx2/driver/ReadWriteQueue.h
new file mode 100644
index 00000000..4f1a98c1
--- /dev/null
+++ b/usb/umdf_fx2/driver/ReadWriteQueue.h
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.h
+
+Abstract:
+
+ This file defines the queue callback interface.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+
+#define MAX_TRANSFER_SIZE(x) 64*1024*1024
+
+//
+// Queue Callback Object.
+//
+
+class CMyReadWriteQueue :
+ public IQueueCallbackRead,
+ public IQueueCallbackWrite,
+ public IRequestCallbackRequestCompletion,
+ public IQueueCallbackIoStop,
+ public CMyQueue
+{
+protected:
+ HRESULT
+ Initialize(
+ );
+
+ void
+ ForwardFormattedRequest(
+ _In_ IWDFIoRequest* pRequest,
+ _In_ IWDFIoTarget* pIoTarget
+ );
+
+public:
+
+ CMyReadWriteQueue(
+ _In_ PCMyDevice Device
+ );
+
+ virtual ~CMyReadWriteQueue();
+
+ static
+ HRESULT
+ CreateInstance(
+ _In_ PCMyDevice Device,
+ _Out_ PCMyReadWriteQueue *Queue
+ );
+
+ HRESULT
+ Configure(
+ VOID
+ )
+ {
+ return CMyQueue::Configure();
+ }
+
+ IQueueCallbackWrite *
+ QueryIQueueCallbackWrite(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackWrite *>(this);
+ }
+
+ IQueueCallbackRead *
+ QueryIQueueCallbackRead(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackRead *>(this);
+ }
+
+ IRequestCallbackRequestCompletion *
+ QueryIRequestCallbackRequestCompletion(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IRequestCallbackRequestCompletion *>(this);
+ }
+
+ IQueueCallbackIoStop*
+ QueryIQueueCallbackIoStop(
+ VOID
+ )
+ {
+ AddRef();
+ return static_cast<IQueueCallbackIoStop *>(this);
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHOD_(ULONG,AddRef) (VOID) {return CUnknown::AddRef();}
+
+ _At_(this, __drv_freesMem(object))
+ STDMETHOD_(ULONG,Release) (VOID) {return CUnknown::Release();}
+
+ STDMETHOD_(HRESULT, QueryInterface)(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+
+
+ //
+ // Wdf Callbacks
+ //
+
+ //
+ // IQueueCallbackWrite
+ //
+ STDMETHOD_ (void, OnWrite)(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T NumOfBytesToWrite
+ );
+
+ //
+ // IQueueCallbackRead
+ //
+ STDMETHOD_ (void, OnRead)(
+ _In_ IWDFIoQueue *pWdfQueue,
+ _In_ IWDFIoRequest *pWdfRequest,
+ _In_ SIZE_T NumOfBytesToRead
+ );
+
+ //
+ //IRequestCallbackRequestCompletion
+ //
+
+ STDMETHOD_ (void, OnCompletion)(
+ _In_ IWDFIoRequest* pWdfRequest,
+ _In_ IWDFIoTarget* pIoTarget,
+ _In_ IWDFRequestCompletionParams* pParams,
+ _In_ PVOID pContext
+ );
+
+ //
+ //IQueueCallbackIoStop
+ //
+
+ STDMETHOD_ (void, OnIoStop)(
+ _In_ IWDFIoQueue * pWdfQueue,
+ _In_ IWDFIoRequest * pWdfRequest,
+ _In_ ULONG ActionFlags
+ );
+
+};
diff --git a/usb/umdf_fx2/driver/WUDFOsrUsbFx2.inx b/usb/umdf_fx2/driver/WUDFOsrUsbFx2.inx
new file mode 100644
index 00000000..1ade7da6
--- /dev/null
+++ b/usb/umdf_fx2/driver/WUDFOsrUsbFx2.inx
@@ -0,0 +1,115 @@
+;
+; WUDFOsrUsbFx2.inf - Install the OSR USB user-mode driver
+;
+
+[Version]
+Signature="$Windows NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFTUMDF%
+DriverVer=03/25/2005,0.0.0.1
+CatalogFile=wudf.cat
+
+[Manufacturer]
+%MSFTUMDF%=Microsoft,NT$ARCH$
+
+[Microsoft.NT$ARCH$]
+%OsrUsbDeviceName%=OsrUsb_Install, USB\Vid_045e&Pid_94aa&mi_00
+%OsrUsbDeviceName%=OsrUsb_Install, USB\VID_0547&PID_1002
+
+[ClassInstall32]
+AddReg=SampleClass_RegistryAdd
+
+[SampleClass_RegistryAdd]
+HKR,,,,%ClassName%
+HKR,,Icon,,"-10"
+
+[SourceDisksFiles]
+WUDFOsrUsbFx2.dll=1
+WudfUpdate_$UMDFCOINSTALLERVERSION$.dll=1
+
+[SourceDisksNames]
+1 = %MediaDescription%
+
+; =================== UMDF OsrUsb Device ==================================
+
+[OsrUsb_Install.NT]
+CopyFiles=UMDriverCopy
+Include=WINUSB.INF ; Import sections from WINUSB.INF
+Needs=WINUSB.NT ; Run the CopyFiles & AddReg directives for WinUsb.INF
+
+
+[OsrUsb_Install.NT.hw]
+AddReg=OsrUsb_Device_AddReg
+
+[OsrUsb_Install.NT.Services]
+AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall ; flag 0x2 sets this as the service for the device
+AddService=WinUsb,0x000001f8,WinUsb_ServiceInstall ; this service is installed because its a filter.
+
+[OsrUsb_Install.NT.Wdf]
+KmdfService=WINUSB, WinUsb_Install
+UmdfDispatcher=WinUsb
+UmdfService=WUDFOsrUsbFx2, WUDFOsrUsbFx2_Install
+UmdfServiceOrder=WUDFOsrUsbFx2
+
+; Enable impersonation for the PLAY_FILE IOCTL
+UmdfImpersonationLevel=Impersonation
+
+[OsrUsb_Install.NT.CoInstallers]
+AddReg=CoInstallers_AddReg
+CopyFiles=CoInstallers_CopyFiles
+
+; Needed for Win7 support
+[WinUsb_Install]
+KmdfLibraryVersion = 1.9
+
+[WUDFOsrUsbFx2_Install]
+UmdfLibraryVersion=$UMDFVERSION$
+DriverCLSID = "{0865b2b0-6b73-428f-a3ea-2172832d6bfc}"
+ServiceBinary = "%12%\UMDF\WUDFOsrUsbFx2.dll"
+
+[OsrUsb_Device_AddReg]
+HKR,,"LowerFilters",0x00010008,"WinUsb" ; FLG_ADDREG_TYPE_MULTI_SZ | FLG_ADDREG_APPEND
+HKR,,"WinUsbPowerPolicyOwnershipDisabled",0x00010001,1 ; our driver takes ownership of power policy. Tell WINUSB not to
+
+; When the UMDF Idle/Wake APIs are called with WdfDefault setting
+; These keys tell UMDF to enable idle and wake by default
+HKR,WudfPowerPolicySettings,"WdfDefaultIdleInWorkingState",0x00010001,1
+HKR,WudfPowerPolicySettings,"WdfDefaultWakeFromSleepState",0x00010001,1
+
+[WUDFRD_ServiceInstall]
+DisplayName = %WudfRdDisplayName%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\WUDFRd.sys
+
+[WinUsb_ServiceInstall]
+DisplayName = %WinUsb_SvcDesc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 1
+ServiceBinary = %12%\WinUSB.sys
+
+[CoInstallers_AddReg]
+HKR,,CoInstallers32,0x00010000,"WudfUpdate_$UMDFCOINSTALLERVERSION$.dll"
+
+[CoInstallers_CopyFiles]
+WudfUpdate_$UMDFCOINSTALLERVERSION$.dll
+
+[DestinationDirs]
+UMDriverCopy=12,UMDF ; copy to driversMdf
+CoInstallers_CopyFiles=11
+
+[UMDriverCopy]
+WUDFOsrUsbFx2.dll,,,0x00004000 ; COPYFLG_IN_USE_RENAME
+
+; =================== Generic ==================================
+
+[Strings]
+MSFTUMDF="Microsoft Internal (WDF:UMDF)"
+MediaDescription="Microsoft Sample Driver Installation Media"
+ClassName="Sample Device"
+WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector"
+OsrUsbDeviceName="UMDF Sample Driver for OSR USB Fx2 Learning Kit"
+WinUsb_SvcDesc="WinUSB Driver"
diff --git a/usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj b/usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj
new file mode 100644
index 00000000..78e68710
--- /dev/null
+++ b/usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6C6B5C2D-F192-4C22-B8ED-A90C10FB9A1E}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <UMDF_VERSION_MAJOR>1</UMDF_VERSION_MAJOR>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{DD1D49D1-69A2-4BF2-9EE8-34692D0104FB}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>UMDF</DriverType>
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems">
+ <ClCompile Include="dllsup.cpp; comsup.cpp; driver.cpp; device.cpp; queue.cpp; ControlQueue.cpp; ReadWriteQueue.cpp">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppScanConfigurationData>internal.h</WppScanConfigurationData>
+ </ClCompile>
+ <Inf Include="WUDFOsrUsbFx2.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\WUDFOsrUsbFx2.inf</CopyOutput>
+ </Inf>
+ <OtherWpp Include="OsrUsbFx2.rc">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppScanConfigurationData>internal.h</WppScanConfigurationData>
+ </OtherWpp>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>WUDFOsrUsbFx2</TargetName>
+ <WIN32_WINNT_VERSION>0x0A00</WIN32_WINNT_VERSION>
+ <NTDDI_VERSION>0x0A000000</NTDDI_VERSION>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <DisableSpecificWarnings>%(DisableSpecificWarnings);4201</DisableSpecificWarnings>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ClCompile>
+ <Midl>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);_UNICODE;UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\..\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\strsafe.lib;$(SDK_LIB_PATH)\kernel32.lib;$(SDK_LIB_PATH)\advapi32.lib;$(SDK_LIB_PATH)\setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="..\deviceMetadata\B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-ms" />
+ <None Include="..\deviceMetadata\B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-ms" />
+ </ItemGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
+ </Link>
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OsrUsbFx2.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="*.txt" Exclude="@(None)" />
+ <None Include="*.htm" Exclude="@(None)" />
+ <None Include="*.html" Exclude="@(None)" />
+ <None Include="*.ico" Exclude="@(None)" />
+ <None Include="*.cur" Exclude="@(None)" />
+ <None Include="*.bmp" Exclude="@(None)" />
+ <None Include="*.dlg" Exclude="@(None)" />
+ <None Include="*.rct" Exclude="@(None)" />
+ <None Include="*.gif" Exclude="@(None)" />
+ <None Include="*.jpg" Exclude="@(None)" />
+ <None Include="*.jpeg" Exclude="@(None)" />
+ <None Include="*.wav" Exclude="@(None)" />
+ <None Include="*.jpe" Exclude="@(None)" />
+ <None Include="*.tiff" Exclude="@(None)" />
+ <None Include="*.tif" Exclude="@(None)" />
+ <None Include="*.png" Exclude="@(None)" />
+ <None Include="*.rc2" Exclude="@(None)" />
+ <None Include="*.def" Exclude="@(None)" />
+ <None Include="*.bat" Exclude="@(None)" />
+ <None Include="*.hpj" Exclude="@(None)" />
+ <None Include="*.asmx" Exclude="@(None)" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj.Filters b/usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj.Filters
new file mode 100644
index 00000000..1e50204c
--- /dev/null
+++ b/usb/umdf_fx2/driver/WUDFOsrUsbFx2.vcxproj.Filters
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{23E0CA5E-560F-46BF-8A5D-0C9892A60610}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{DE2D9516-18E4-493F-8E49-245A3A552F1A}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{0D7905F4-200D-4439-A264-543F6CC50803}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{622540FC-F451-4D00-B0A6-DED0A2B5BDBA}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="comsup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ControlQueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllsup.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="queue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ReadWriteQueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <None Include="exports.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\WUDFOsrUsbFx2.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include="WUDFOsrUsbFx2.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="OsrUsbFx2.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf_fx2/driver/comsup.cpp b/usb/umdf_fx2/driver/comsup.cpp
new file mode 100644
index 00000000..9c9aec3b
--- /dev/null
+++ b/usb/umdf_fx2/driver/comsup.cpp
@@ -0,0 +1,344 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ComSup.cpp
+
+Abstract:
+
+ This module contains implementations for the functions and methods
+ used for providing COM support.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+
+#include "comsup.tmh"
+
+//
+// Implementation of CUnknown methods.
+//
+
+CUnknown::CUnknown(
+ VOID
+ ) : m_ReferenceCount(1)
+/*++
+
+ Routine Description:
+
+ Constructor for an instance of the CUnknown class. This simply initializes
+ the reference count of the object to 1. The caller is expected to
+ call Release() if it wants to delete the object once it has been allocated.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ None
+
+--*/
+{
+ // do nothing.
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CUnknown::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method provides the basic support for query interface on CUnknown.
+ If the interface requested is IUnknown it references the object and
+ returns an interface pointer. Otherwise it returns an error.
+
+ Arguments:
+
+ InterfaceId - the IID being requested
+
+ Object - a location to store the interface pointer to return.
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ if (IsEqualIID(InterfaceId, __uuidof(IUnknown)))
+ {
+ *Object = QueryIUnknown();
+ return S_OK;
+ }
+ else
+ {
+ *Object = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+IUnknown *
+CUnknown::QueryIUnknown(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This helper method references the object and returns a pointer to the
+ object's IUnknown interface.
+
+ This allows other methods to convert a CUnknown pointer into an IUnknown
+ pointer without a typecast and without calling QueryInterface and dealing
+ with the return value.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ A pointer to the object's IUnknown interface.
+
+--*/
+{
+ AddRef();
+ return static_cast<IUnknown *>(this);
+}
+
+ULONG
+STDMETHODCALLTYPE
+CUnknown::AddRef(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method adds one to the object's reference count.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ The new reference count. The caller should only use this for debugging
+ as the object's actual reference count can change while the caller
+ examines the return value.
+
+--*/
+{
+ return InterlockedIncrement(&m_ReferenceCount);
+}
+
+ULONG
+STDMETHODCALLTYPE
+CUnknown::Release(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This method subtracts one to the object's reference count. If the count
+ goes to zero, this method deletes the object.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ The new reference count. If the caller uses this value it should only be
+ to check for zero (i.e. this call caused or will cause deletion) or
+ non-zero (i.e. some other call may have caused deletion, but this one
+ didn't).
+
+--*/
+{
+ ULONG count = InterlockedDecrement(&m_ReferenceCount);
+
+ if (count == 0)
+ {
+ delete this;
+ }
+ return count;
+}
+
+//
+// Implementation of CClassFactory methods.
+//
+
+//
+// Define storage for the factory's static lock count variable.
+//
+
+LONG CClassFactory::s_LockCount = 0;
+
+IClassFactory *
+CClassFactory::QueryIClassFactory(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This helper method references the object and returns a pointer to the
+ object's IClassFactory interface.
+
+ This allows other methods to convert a CClassFactory pointer into an
+ IClassFactory pointer without a typecast and without dealing with the
+ return value QueryInterface.
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ A referenced pointer to the object's IClassFactory interface.
+
+--*/
+{
+ AddRef();
+ return static_cast<IClassFactory *>(this);
+}
+
+HRESULT
+CClassFactory::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This method attempts to retrieve the requested interface from the object.
+
+ If the interface is found then the reference count on that interface (and
+ thus the object itself) is incremented.
+
+ Arguments:
+
+ InterfaceId - the interface the caller is requesting.
+
+ Object - a location to store the interface pointer.
+
+ Return Value:
+
+ S_OK or E_NOINTERFACE
+
+--*/
+{
+ //
+ // This class only supports IClassFactory so check for that.
+ //
+
+ if (IsEqualIID(InterfaceId, __uuidof(IClassFactory)))
+ {
+ *Object = QueryIClassFactory();
+ return S_OK;
+ }
+ else
+ {
+ //
+ // See if the base class supports the interface.
+ //
+
+ return CUnknown::QueryInterface(InterfaceId, Object);
+ }
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CClassFactory::CreateInstance(
+ _In_opt_ IUnknown * /* OuterObject */,
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ )
+/*++
+
+ Routine Description:
+
+ This COM method is the factory routine - it creates instances of the driver
+ callback class and returns the specified interface on them.
+
+ Arguments:
+
+ OuterObject - only used for aggregation, which our driver callback class
+ does not support.
+
+ InterfaceId - the interface ID the caller would like to get from our
+ new object.
+
+ Object - a location to store the referenced interface pointer to the new
+ object.
+
+ Return Value:
+
+ Status.
+
+--*/
+{
+ HRESULT hr;
+
+ PCMyDriver driver;
+
+ *Object = NULL;
+
+ hr = CMyDriver::CreateInstance(&driver);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = driver->QueryInterface(InterfaceId, Object);
+ driver->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CClassFactory::LockServer(
+ _In_ BOOL Lock
+ )
+/*++
+
+ Routine Description:
+
+ This COM method can be used to keep the DLL in memory. However since the
+ driver's DllCanUnloadNow function always returns false, this has little
+ effect. Still it tracks the number of lock and unlock operations.
+
+ Arguments:
+
+ Lock - Whether the caller wants to lock or unlock the "server"
+
+ Return Value:
+
+ S_OK
+
+--*/
+{
+ if (Lock)
+ {
+ InterlockedIncrement(&s_LockCount);
+ }
+ else
+ {
+ InterlockedDecrement(&s_LockCount);
+ }
+ return S_OK;
+}
+
diff --git a/usb/umdf_fx2/driver/comsup.h b/usb/umdf_fx2/driver/comsup.h
new file mode 100644
index 00000000..dedf78c8
--- /dev/null
+++ b/usb/umdf_fx2/driver/comsup.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ ComSup.h
+
+Abstract:
+
+ This module contains classes and functions use for providing COM support
+ code.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Forward type declarations. They are here rather than in internal.h as
+// you only need them if you choose to use these support classes.
+//
+
+typedef class CUnknown *PCUnknown;
+typedef class CClassFactory *PCClassFactory;
+
+//
+// Base class to implement IUnknown. You can choose to derive your COM
+// classes from this class, or simply implement IUnknown in each of your
+// classes.
+//
+
+class CUnknown : public IUnknown
+{
+
+//
+// Private data members and methods. These are only accessible by the methods
+// of this class.
+//
+private:
+
+ //
+ // The reference count for this object. Initialized to 1 in the
+ // constructor.
+ //
+
+ LONG m_ReferenceCount;
+
+//
+// Protected data members and methods. These are accessible by the subclasses
+// but not by other classes.
+//
+protected:
+
+ //
+ // The constructor and destructor are protected to ensure that only the
+ // subclasses of CUnknown can create and destroy instances.
+ //
+
+ CUnknown(
+ VOID
+ );
+
+ //
+ // The destructor MUST be virtual. Since any instance of a CUnknown
+ // derived class should only be deleted from within CUnknown::Release,
+ // the destructor MUST be virtual or only CUnknown::~CUnknown will get
+ // invoked on deletion.
+ //
+ // If you see that your CMyDevice specific destructor is never being
+ // called, make sure you haven't deleted the virtual destructor here.
+ //
+
+ virtual
+ ~CUnknown(
+ VOID
+ )
+ {
+ // Do nothing
+ }
+
+//
+// Public Methods. These are accessible by any class.
+//
+public:
+
+ IUnknown *
+ QueryIUnknown(
+ VOID
+ );
+
+//
+// COM Methods.
+//
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ );
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+};
+
+//
+// Class factory support class. Create an instance of this from your
+// DllGetClassObject method and modify the implementation to create
+// an instance of your driver event handler class.
+//
+
+class CClassFactory : public CUnknown, public IClassFactory
+{
+//
+// Private data members and methods. These are only accessible by the methods
+// of this class.
+//
+private:
+
+ //
+ // The lock count. This is shared across all instances of IClassFactory
+ // and can be queried through the public IsLocked method.
+ //
+
+ static LONG s_LockCount;
+
+//
+// Public Methods. These are accessible by any class.
+//
+public:
+
+ IClassFactory *
+ QueryIClassFactory(
+ VOID
+ );
+
+//
+// COM Methods.
+//
+public:
+
+ //
+ // IUnknown methods
+ //
+
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ AddRef(
+ VOID
+ )
+ {
+ return __super::AddRef();
+ }
+
+ _At_(this, __drv_freesMem(object))
+ virtual
+ ULONG
+ STDMETHODCALLTYPE
+ Release(
+ VOID
+ )
+ {
+ return __super::Release();
+ }
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+
+ //
+ // IClassFactory methods.
+ //
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ CreateInstance(
+ _In_opt_ IUnknown *OuterObject,
+ _In_ REFIID InterfaceId,
+ _Out_ PVOID *Object
+ );
+
+ virtual
+ HRESULT
+ STDMETHODCALLTYPE
+ LockServer(
+ _In_ BOOL Lock
+ );
+};
diff --git a/usb/umdf_fx2/driver/dllsup.cpp b/usb/umdf_fx2/driver/dllsup.cpp
new file mode 100644
index 00000000..22dfb3b0
--- /dev/null
+++ b/usb/umdf_fx2/driver/dllsup.cpp
@@ -0,0 +1,202 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved.
+
+Module Name:
+
+ dllsup.cpp
+
+Abstract:
+
+ This module contains the implementation of the UMDF OSR Fx2
+ Driver's entry point and its exported functions for providing COM support.
+
+ This module can be copied without modification to a new UMDF driver. It
+ depends on some of the code in comsup.cpp & comsup.h to handle DLL
+ registration and creating the first class factory.
+
+ This module is dependent on the following defines:
+
+ MYDRIVER_TRACING_ID - A wide string passed to WPP when initializing
+ tracing. For example the driver uses
+ L"Microsoft\\UMDF\\OsrUsb"
+
+ MYDRIVER_CLASS_ID - A GUID encoded in struct format used to
+ initialize the driver's ClassID.
+
+ These are defined in internal.h for this sample. If you choose
+ to use a different primary include file, you should ensure they are
+ defined there as well.
+
+Environment:
+
+ WDF User-Mode Driver Framework (WDF:UMDF)
+
+--*/
+
+#include "internal.h"
+#include "dllsup.tmh"
+
+const GUID CLSID_MyDriverCoClass = MYDRIVER_CLASS_ID;
+
+BOOL
+WINAPI
+DllMain(
+ HINSTANCE ModuleHandle,
+ DWORD Reason,
+ PVOID /* Reserved */
+ )
+/*++
+
+ Routine Description:
+
+ This is the entry point and exit point for the I/O trace driver. This
+ does very little as the I/O trace driver has minimal global data.
+
+ This method initializes tracing, and saves the module handle away in a
+ global variable so that it can be referenced should the COM registration
+ code (Dll[Un]RegisterServer) be called.
+
+ Arguments:
+
+ ModuleHandle - the DLL handle for this module.
+
+ Reason - the reason this entry point was called.
+
+ Reserved - unused
+
+ Return Value:
+
+ TRUE
+
+--*/
+{
+ UNREFERENCED_PARAMETER(ModuleHandle);
+
+ if (DLL_PROCESS_ATTACH == Reason)
+ {
+ //
+ // Initialize tracing.
+ //
+
+ WPP_INIT_TRACING(MYDRIVER_TRACING_ID);
+ }
+ else if (DLL_PROCESS_DETACH == Reason)
+ {
+ //
+ // Cleanup tracing.
+ //
+
+ WPP_CLEANUP();
+ }
+
+ return TRUE;
+}
+
+HRESULT
+STDAPICALLTYPE
+DllCanUnloadNow(
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ Called by the COM runtime when determining whether or not this module
+ can be unloaded. Our answer is always "no".
+
+ Arguments:
+
+ None
+
+ Return Value:
+
+ S_FALSE
+
+--*/
+{
+ return S_FALSE;
+}
+
+HRESULT
+STDAPICALLTYPE
+DllGetClassObject(
+ _In_ REFCLSID ClassId,
+ _In_ REFIID InterfaceId,
+ _Outptr_ LPVOID *Interface
+ )
+/*++
+
+ Routine Description:
+
+ This routine is called by COM in order to instantiate the
+ OSR Fx2 driver callback object and do an initial query interface on it.
+
+ This method only creates an instance of the driver's class factory, as this
+ is the minimum required to support UMDF.
+
+ Arguments:
+
+ ClassId - the CLSID of the object being "gotten"
+
+ InterfaceId - the interface the caller wants from that object.
+
+ Interface - a location to store the referenced interface pointer
+
+ Return Value:
+
+ S_OK if the function succeeds or error indicating the cause of the
+ failure.
+
+--*/
+{
+ PCClassFactory factory;
+
+ HRESULT hr = S_OK;
+
+ *Interface = NULL;
+
+ //
+ // If the CLSID doesn't match that of our "coclass" (defined in the IDL
+ // file) then we can't create the object the caller wants. This may
+ // indicate that the COM registration is incorrect, and another CLSID
+ // is referencing this drvier.
+ //
+
+ if (IsEqualCLSID(ClassId, CLSID_MyDriverCoClass) == false)
+ {
+ Trace(
+ TRACE_LEVEL_ERROR,
+ L"ERROR: Called to create instance of unrecognized class (%!GUID!)",
+ &ClassId
+ );
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ //
+ // Create an instance of the class factory for the caller.
+ //
+
+ factory = new CClassFactory();
+
+ if (NULL == factory)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ //
+ // Query the object we created for the interface the caller wants. After
+ // that we release the object. This will drive the reference count to
+ // 1 (if the QI succeeded an referenced the object) or 0 (if the QI failed).
+ // In the later case the object is automatically deleted.
+ //
+
+ if (SUCCEEDED(hr))
+ {
+ hr = factory->QueryInterface(InterfaceId, Interface);
+ factory->Release();
+ }
+
+ return hr;
+}
diff --git a/usb/umdf_fx2/driver/exports.def b/usb/umdf_fx2/driver/exports.def
new file mode 100644
index 00000000..15f923d3
--- /dev/null
+++ b/usb/umdf_fx2/driver/exports.def
@@ -0,0 +1,4 @@
+; WudfOsrUsbDriver.def : Declares the module parameters.
+
+EXPORTS
+ DllGetClassObject PRIVATE
diff --git a/usb/umdf_fx2/driver/internal.h b/usb/umdf_fx2/driver/internal.h
new file mode 100644
index 00000000..2d57793d
--- /dev/null
+++ b/usb/umdf_fx2/driver/internal.h
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (C) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ Internal.h
+
+Abstract:
+
+ This module contains the local type definitions for the UMDF OSR Fx2
+ driver sample.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+//
+// Include the WUDF Headers
+//
+
+#include "wudfddi.h"
+
+//
+// Include SetupDi functions.
+//
+
+#include "setupapi.h"
+
+//
+// Use specstrings for in/out annotation of function parameters.
+//
+
+#include "specstrings.h"
+
+//
+// Include the safestring functions.
+//
+
+#include "strsafe.h"
+
+//
+// Get limits on common data types (ULONG_MAX for example)
+//
+
+#include "limits.h"
+
+//
+// We need usb I/O targets to talk to the OSR device.
+//
+
+#include "wudfusb.h"
+
+//
+// Include the header shared between the drivers and the test applications.
+//
+
+#include "public.h"
+
+//
+// Include the header shared between the drivers and the test applications.
+//
+
+#include "WUDFOsrUsbPublic.h"
+
+//
+// Forward definitions of classes in the other header files.
+//
+
+typedef class CMyDriver *PCMyDriver;
+typedef class CMyDevice *PCMyDevice;
+typedef class CMyQueue *PCMyQueue;
+
+typedef class CMyControlQueue *PCMyControlQueue;
+typedef class CMyReadWriteQueue *PCMyReadWriteQueue;
+
+typedef class CCancelCallback *PCCancelCallback;
+
+//
+// Define the tracing flags.
+//
+// TODO: Choose a different trace control GUID
+//
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ WudfOsrUsbFx2TraceGuid, (da5fbdfd,1eae,4ecf,b426,a3818f325ddb), \
+ \
+ WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
+ WPP_DEFINE_BIT(TEST_TRACE_DRIVER) \
+ WPP_DEFINE_BIT(TEST_TRACE_DEVICE) \
+ WPP_DEFINE_BIT(TEST_TRACE_QUEUE) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
+ WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
+ (WPP_LEVEL_ENABLED(flag) && \
+ WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
+ WPP_LEVEL_LOGGER(flags)
+
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
+ (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
+// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
+// end_wpp
+//
+
+//
+// Driver specific #defines
+//
+// TODO: Change these values to be appropriate for your driver.
+//
+
+#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF\\OsrUsb"
+#define MYDRIVER_CLASS_ID {0x0865b2b0, 0x6b73, 0x428f, {0xa3, 0xea, 0x21, 0x72, 0x83, 0x2d, 0x6b, 0xfc}}
+
+//
+// Include the type specific headers.
+//
+
+#include "comsup.h"
+#include "driver.h"
+#include "device.h"
+#include "queue.h"
+#include "ControlQueue.h"
+#include "ReadWriteQueue.h"
+#include "list.h"
+
+__forceinline
+#ifdef _PREFAST_
+__declspec(noreturn)
+#endif
+VOID
+WdfTestNoReturn(
+ VOID
+ )
+{
+ // do nothing.
+}
+
+#define WUDF_TEST_DRIVER_ASSERT(p) \
+{ \
+ if ( !(p) ) \
+ { \
+ DebugBreak(); \
+ WdfTestNoReturn(); \
+ } \
+}
+
+#define SAFE_RELEASE(p) {if ((p)) { (p)->Release(); (p) = NULL; }}
+
+#define IDLE_TIMEOUT_IN_MSEC 10*1000
diff --git a/usb/umdf_fx2/driver/queue.cpp b/usb/umdf_fx2/driver/queue.cpp
new file mode 100644
index 00000000..c56b38bb
--- /dev/null
+++ b/usb/umdf_fx2/driver/queue.cpp
@@ -0,0 +1,147 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.cpp
+
+Abstract:
+
+ This file implements the I/O queue interface and performs
+ the read/write/ioctl operations.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#include "internal.h"
+#include "queue.tmh"
+
+CMyQueue::CMyQueue(
+ _In_ PCMyDevice Device
+ ) :
+ m_FxQueue(NULL),
+ m_Device(Device)
+{
+}
+
+//
+// Queue destructor.
+// Free up the buffer, wait for thread to terminate and
+//
+
+CMyQueue::~CMyQueue(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+ IUnknown implementation of Release
+
+Aruments:
+
+
+Return Value:
+
+ ULONG (reference count after Release)
+
+--*/
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TEST_TRACE_QUEUE,
+ "%!FUNC! Entry"
+ );
+
+}
+
+
+HRESULT
+STDMETHODCALLTYPE
+CMyQueue::QueryInterface(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ )
+/*++
+
+Routine Description:
+
+
+ Query Interface
+
+Aruments:
+
+ Follows COM specifications
+
+Return Value:
+
+ HRESULT indicatin success or failure
+
+--*/
+{
+ HRESULT hr;
+
+ hr = CUnknown::QueryInterface(InterfaceId, Object);
+
+ return hr;
+}
+
+//
+// Initialize
+//
+
+HRESULT
+CMyQueue::Initialize(
+ _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType,
+ _In_ bool Default,
+ _In_ bool PowerManaged
+ )
+{
+ IWDFIoQueue *fxQueue;
+ HRESULT hr;
+
+ //
+ // Create the I/O Queue object.
+ //
+
+ {
+ IUnknown *callback = QueryIUnknown();
+
+ hr = m_Device->GetFxDevice()->CreateIoQueue(
+ callback,
+ Default,
+ DispatchType,
+ PowerManaged,
+ FALSE,
+ &fxQueue
+ );
+ callback->Release();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ m_FxQueue = fxQueue;
+
+ //
+ // Release the creation reference on the queue. This object will be
+ // destroyed before the queue so we don't need to have a reference out
+ // on it.
+ //
+
+ fxQueue->Release();
+ }
+
+ return hr;
+}
+
+HRESULT
+CMyQueue::Configure(
+ VOID
+ )
+{
+ return S_OK;
+}
diff --git a/usb/umdf_fx2/driver/queue.h b/usb/umdf_fx2/driver/queue.h
new file mode 100644
index 00000000..5659224b
--- /dev/null
+++ b/usb/umdf_fx2/driver/queue.h
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) Microsoft Corporation, All Rights Reserved
+
+Module Name:
+
+ queue.h
+
+Abstract:
+
+ This file defines the queue callback interface.
+
+Environment:
+
+ Windows User-Mode Driver Framework (WUDF)
+
+--*/
+
+#pragma once
+
+//
+// Queue Callback Object.
+//
+
+class CMyQueue :
+ public CUnknown
+{
+protected:
+ //
+ // Unreferenced pointer to the partner Fx device.
+ //
+
+ IWDFIoQueue *m_FxQueue;
+
+ //
+ // Unreferenced pointer to the parent device.
+ //
+
+ PCMyDevice m_Device;
+
+ HRESULT
+ Initialize(
+ _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType,
+ _In_ bool Default,
+ _In_ bool PowerManaged
+ );
+
+protected:
+
+ CMyQueue(
+ _In_ PCMyDevice Device
+ );
+
+ virtual ~CMyQueue();
+
+ HRESULT
+ Configure(
+ VOID
+ );
+
+public:
+
+ IWDFIoQueue *
+ GetFxQueue(
+ VOID
+ )
+ {
+ return m_FxQueue;
+ }
+
+
+ PCMyDevice
+ GetDevice(
+ VOID
+ )
+ {
+ return m_Device;
+ }
+
+ //
+ // IUnknown
+ //
+
+ STDMETHOD_(ULONG,AddRef) (VOID) {return CUnknown::AddRef();}
+
+ _At_(this, __drv_freesMem(object))
+ STDMETHOD_(ULONG,Release) (VOID) {return CUnknown::Release();}
+
+ STDMETHOD_(HRESULT, QueryInterface)(
+ _In_ REFIID InterfaceId,
+ _Outptr_ PVOID *Object
+ );
+};