summaryrefslogtreecommitdiff
path: root/usb/kmdf_enumswitches
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
committerDave Wilson <[email protected]>2015-03-17 19:50:07 -0700
commit97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch)
tree46f3701832d70b420eb0fc0eb93261f9da45db3f /usb/kmdf_enumswitches
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'usb/kmdf_enumswitches')
-rw-r--r--usb/kmdf_enumswitches/ReadMe.md47
-rw-r--r--usb/kmdf_enumswitches/inc/prototypes.h14
-rw-r--r--usb/kmdf_enumswitches/inc/public.h173
-rw-r--r--usb/kmdf_enumswitches/kmdf_enumswitches.sln28
-rw-r--r--usb/kmdf_enumswitches/sys/Device.c384
-rw-r--r--usb/kmdf_enumswitches/sys/driver.c188
-rw-r--r--usb/kmdf_enumswitches/sys/interrupt.c195
-rw-r--r--usb/kmdf_enumswitches/sys/kmdf_enumswitches.inx112
-rw-r--r--usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj229
-rw-r--r--usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj.Filters43
-rw-r--r--usb/kmdf_enumswitches/sys/osrusbfx2.h227
-rw-r--r--usb/kmdf_enumswitches/sys/rawpdo.c330
-rw-r--r--usb/kmdf_enumswitches/sys/rawpdo.h60
-rw-r--r--usb/kmdf_enumswitches/sys/trace.h115
14 files changed, 2145 insertions, 0 deletions
diff --git a/usb/kmdf_enumswitches/ReadMe.md b/usb/kmdf_enumswitches/ReadMe.md
new file mode 100644
index 00000000..2107d9b8
--- /dev/null
+++ b/usb/kmdf_enumswitches/ReadMe.md
@@ -0,0 +1,47 @@
+Sample KMDF Bus Driver for OSR USB-FX2
+======================================
+
+The kmdf\_enumswitches sample demonstrates how to use Kernel-Mode Driver Framework (KMDF) as a bus driver using the OSR USB-FX2 device.
+
+This sample is written for the OSR USB-FX2 Learning Kit. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>.
+
+Testing the Device
+------------------
+
+To test the device, follow these steps:
+
+1. If you test signed your driver package, you must enable installation of test signed drivers on the target machine. To do so, either press F8 as the target machine comes up from a reboot, or specify **Bcdedit.exe -set TESTSIGNING ON** and reboot. If you use F8, the change only applies until the next reboot.
+2. Plug in the OSR USB-FX-2 Learning Kit (must be version 2.00 or later).
+3. In Device Manager, select **Update Driver Software**, **Browse my computer for driver software**, **Let me pick from a list of device drivers on my computer**, **Have Disk**. Navigate to the directory that contains your driver package and select the INF file.
+4. After the driver installs, verify that the device appears under the **Sample Device** node in Device Manager.
+5. Flip the switches on the OSR USB-FX-2 hardware board and watch the raw PDO entries appear and disappear under **Sample Device** in Device Manager.
+6. Right-click a raw PDO entry, select **Properties**, and then click the **Events** tab. Under **Information**, examine the hardware ID for the PDO. It should be something like this:
+
+ ``` {.syntax xml:space="preserve"}
+ 6FDE7521-1B65-48ae-B628-80BE62016026}\OsrUsbFxRawPdo\6&227995e2&0&08
+ ```
+
+ The last digit matches the number of the switch that you toggled.
+
+Hardware Overview
+-----------------
+
+Here is the overview of the device:
+
+- Device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+- Contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+- Firmware supports vendor commands to query or set LED Bar graph display, 7-segment LED display and query toggle switch states.
+- Interrupt Endpoint:
+ - Sends an 8-bit value that represents the state of the switches.
+ - Sent on startup, resume from suspend, and whenever the switch pack setting changes.
+ - Firmware does not de-bounce the switch pack.
+ - One switch change can result in multiple bytes being sent.
+ - Bits are in the reverse order of the labels on the pack
+
+ E.g. bit 0x80 is labeled 1 on the pack
+
+- Bulk Endpoints are configured for loopback:
+ - Device moves data from IN endpoint to OUT endpoint.
+ - Device does not change the values of the data it receives nor does it internally create any data.
+ - Endpoints are always double buffered.
+ - Maximum packet size depends on speed (64 Full speed, 512 High speed).
diff --git a/usb/kmdf_enumswitches/inc/prototypes.h b/usb/kmdf_enumswitches/inc/prototypes.h
new file mode 100644
index 00000000..cc99cdfe
--- /dev/null
+++ b/usb/kmdf_enumswitches/inc/prototypes.h
@@ -0,0 +1,14 @@
+DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_DRIVER_DEVICE_ADD EvtDeviceAdd;
+
+EVT_WDF_DEVICE_CONTEXT_CLEANUP EvtDriverContextCleanup;
+EVT_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware;
+
+EVT_WDF_IO_QUEUE_IO_READ EvtIoRead;
+EVT_WDF_IO_QUEUE_IO_WRITE EvtIoWrite;
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl;
+
+EVT_WDF_REQUEST_COMPLETION_ROUTINE EvtRequestReadCompletionRoutine;
+EVT_WDF_REQUEST_COMPLETION_ROUTINE EvtRequestWriteCompletionRoutine;
+
diff --git a/usb/kmdf_enumswitches/inc/public.h b/usb/kmdf_enumswitches/inc/public.h
new file mode 100644
index 00000000..12ddf21f
--- /dev/null
+++ b/usb/kmdf_enumswitches/inc/public.h
@@ -0,0 +1,173 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ public.h
+
+Abstract:
+
+Environment:
+
+ User & Kernel mode
+
+--*/
+
+#ifndef _PUBLIC_H
+#define _PUBLIC_H
+
+#include <initguid.h>
+
+// {573E8C73-0CB4-4471-A1BF-FAB26C31D384}
+DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2,
+ 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84);
+
+#pragma warning(push)
+#pragma warning(disable:4201) // nameless struct/union
+#pragma warning(disable:4214) // bit field types other than int
+
+//
+// Define the structures that will be used by the IOCTL
+// interface to the driver
+//
+
+//
+// BAR_GRAPH_STATE
+//
+// BAR_GRAPH_STATE is a bit field structure with each
+// bit corresponding to one of the bar graph on the
+// OSRFX2 Development Board
+//
+#include <pshpack1.h>
+typedef struct _BAR_GRAPH_STATE {
+
+ union {
+
+ struct {
+ //
+ // Individual bars starting from the
+ // top of the stack of bars
+ //
+ // NOTE: There are actually 10 bars,
+ // but the very top two do not light
+ // and are not counted here
+ //
+ UCHAR Bar1 : 1;
+ UCHAR Bar2 : 1;
+ UCHAR Bar3 : 1;
+ UCHAR Bar4 : 1;
+ UCHAR Bar5 : 1;
+ UCHAR Bar6 : 1;
+ UCHAR Bar7 : 1;
+ UCHAR Bar8 : 1;
+ };
+
+ //
+ // The state of all the bar graph as a single
+ // UCHAR
+ //
+ UCHAR BarsAsUChar;
+
+ };
+
+}BAR_GRAPH_STATE, *PBAR_GRAPH_STATE;
+
+//
+// SWITCH_STATE
+//
+// SWITCH_STATE is a bit field structure with each
+// bit corresponding to one of the switches on the
+// OSRFX2 Development Board
+//
+typedef struct _SWITCH_STATE {
+
+ union {
+ struct {
+ //
+ // Individual switches starting from the
+ // left of the set of switches
+ //
+ UCHAR Switch1 : 1;
+ UCHAR Switch2 : 1;
+ UCHAR Switch3 : 1;
+ UCHAR Switch4 : 1;
+ UCHAR Switch5 : 1;
+ UCHAR Switch6 : 1;
+ UCHAR Switch7 : 1;
+ UCHAR Switch8 : 1;
+ };
+
+ //
+ // The state of all the switches as a single
+ // UCHAR
+ //
+ UCHAR SwitchesAsUChar;
+
+ };
+
+
+}SWITCH_STATE, *PSWITCH_STATE;
+
+#include <poppack.h>
+
+#pragma warning(pop)
+
+#define IOCTL_INDEX 0x800
+#define FILE_DEVICE_OSRUSBFX2 0x65500
+
+#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 1, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 3, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 4, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 5, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 6, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 7, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS)
+
+
+#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
+ IOCTL_INDEX + 8, \
+ METHOD_BUFFERED, \
+ FILE_WRITE_ACCESS)
+
+#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\
+ IOCTL_INDEX + 9, \
+ METHOD_OUT_DIRECT, \
+ FILE_READ_ACCESS)
+
+#endif
diff --git a/usb/kmdf_enumswitches/kmdf_enumswitches.sln b/usb/kmdf_enumswitches/kmdf_enumswitches.sln
new file mode 100644
index 00000000..0b3f4a9a
--- /dev/null
+++ b/usb/kmdf_enumswitches/kmdf_enumswitches.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kmdf_enumswitches", "sys\kmdf_enumswitches.vcxproj", "{6A32E70D-E961-4940-A1E8-AB1A7CED390D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Debug|Win32.Build.0 = Debug|Win32
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Release|Win32.ActiveCfg = Release|Win32
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Release|Win32.Build.0 = Release|Win32
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Debug|x64.ActiveCfg = Debug|x64
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Debug|x64.Build.0 = Debug|x64
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Release|x64.ActiveCfg = Release|x64
+ {6A32E70D-E961-4940-A1E8-AB1A7CED390D}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/usb/kmdf_enumswitches/sys/Device.c b/usb/kmdf_enumswitches/sys/Device.c
new file mode 100644
index 00000000..0d61fe99
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/Device.c
@@ -0,0 +1,384 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Device.c
+
+Abstract:
+
+ USB device driver for OSR USB-FX2 Learning Kit
+
+Environment:
+
+ Kernel mode only
+
+--*/
+
+#include <osrusbfx2.h>
+#include "rawpdo.h"
+
+#include "device.tmh"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, OsrFxEvtDeviceAdd)
+#pragma alloc_text(PAGE, OsrFxEvtDevicePrepareHardware)
+#pragma alloc_text(PAGE, OsrFxEvtDeviceD0Exit)
+#endif
+
+
+NTSTATUS
+OsrFxEvtDeviceAdd(
+ IN WDFDRIVER Driver,
+ IN PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+Routine Description:
+
+ EvtDeviceAdd is called by the framework in response to AddDevice
+ call from the PnP manager. We create and initialize a device object to
+ represent a new instance of the device. All the software resources
+ should be allocated in this callback.
+
+Arguments:
+
+ Driver - Handle to a framework driver object created in DriverEntry
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ NTSTATUS status;
+ WDFDEVICE device;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"--> OsrFxEvtDeviceAdd routine\n");
+
+ //
+ // Initialize the pnpPowerCallbacks structure. Callback events for PNP
+ // and Power are specified here. If you don't supply any callbacks,
+ // the Framework will take appropriate default actions based on whether
+ // DeviceInit is initialized to be an FDO, a PDO or a filter device
+ // object.
+ //
+
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+ //
+ // For usb devices, PrepareHardware callback is the to place select the
+ // interface and configure the device.
+ //
+ pnpPowerCallbacks.EvtDevicePrepareHardware = OsrFxEvtDevicePrepareHardware;
+
+ //
+ // These two callbacks start and stop the WDFUSBPIPE continuous reader
+ // as we go in and out of the D0-working state.
+ //
+
+ pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
+ pnpPowerCallbacks.EvtDeviceD0Exit = OsrFxEvtDeviceD0Exit;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ OsrFxInitChildList(DeviceInit);
+
+ //
+ // Now specify the size of device extension where we track per device
+ // context.DeviceInit is completely initialized. So call the framework
+ // to create the device and attach it to the lower stack.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
+
+ status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceCreate failed with Status code %!STATUS!\n", status);
+ return status;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "OsrFxEvtDeviceAdd - ends\n");
+
+ return status;
+}
+
+NTSTATUS
+OsrFxEvtDevicePrepareHardware(
+ IN WDFDEVICE Device,
+ IN WDFCMRESLIST ResourceList,
+ IN WDFCMRESLIST ResourceListTranslated
+ )
+/*++
+
+Routine Description:
+
+ In this callback, the driver does whatever is necessary to make the
+ hardware ready to use. In the case of a USB device, this involves
+ reading descriptors and selecting interfaces.
+
+Arguments:
+
+ Device - handle to a device
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status, tempStatus;
+ PDEVICE_CONTEXT pDeviceContext;
+ WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
+
+ UNREFERENCED_PARAMETER(ResourceList);
+ UNREFERENCED_PARAMETER(ResourceListTranslated);
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> EvtDevicePrepareHardware\n");
+
+ pDeviceContext = GetDeviceContext(Device);
+
+ //
+ // Create a USB device handle so that we can communicate with the
+ // underlying USB stack. The WDFUSBDEVICE handle is used to query,
+ // configure, and manage all aspects of the USB device.
+ // These aspects include device properties, bus properties,
+ // and I/O creation and synchronization. We only create device the first
+ // the PrepareHardware is called. If the device is restarted by pnp manager
+ // for resource rebalance, we will use the same device handle but then select
+ // the interfaces again because the USB stack could reconfigure the device on
+ // restart.
+ //
+ if (pDeviceContext->UsbDevice == NULL) {
+ WDF_USB_DEVICE_CREATE_CONFIG config;
+
+ WDF_USB_DEVICE_CREATE_CONFIG_INIT(&config,
+ USBD_CLIENT_CONTRACT_VERSION_602);
+
+ status = WdfUsbTargetDeviceCreateWithParameters(Device,
+ &config,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &pDeviceContext->UsbDevice);
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfUsbTargetDeviceCreateWithParameters failed with Status code %!STATUS!\n", status);
+ return status;
+ }
+ }
+
+ WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams);
+
+ status = WdfUsbTargetDeviceSelectConfig(pDeviceContext->UsbDevice,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &configParams);
+ if(!NT_SUCCESS(status)) {
+ WDF_USB_DEVICE_INFORMATION deviceInfo;
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfUsbTargetDeviceSelectConfig failed %!STATUS! \n",
+ status);
+ //
+ // detect if we are connected to a 1.1 USB port
+ //
+ WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);
+ tempStatus = WdfUsbTargetDeviceRetrieveInformation(pDeviceContext->UsbDevice, &deviceInfo);
+
+ if (NT_SUCCESS(tempStatus)) {
+ //
+ // Since the Osr USB fx2 device is capable of working at high speed, the only reason
+ // the device would not be working at high speed is if the port doesn't
+ // support it. If the port doesn't support high speed it is a 1.1 port
+ //
+ if ((deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) == 0) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ " On a 1.1 USB port on Windows Vista"
+ " this is expected as the OSR USB Fx2 board's Interrupt EndPoint descriptor"
+ " doesn't conform to the USB specification. Windows Vista detects this and"
+ " returns an error. \n"
+ );
+ }
+ }
+
+ return status;
+ }
+
+ pDeviceContext->UsbInterface =
+ configParams.Types.SingleInterface.ConfiguredUsbInterface;
+
+ status = OsrFxConfigContReaderForInterruptEndPoint(pDeviceContext);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- EvtDevicePrepareHardware\n");
+
+ return status;
+}
+
+
+NTSTATUS
+OsrFxEvtDeviceD0Entry(
+ IN WDFDEVICE Device,
+ IN WDF_POWER_DEVICE_STATE PreviousState
+ )
+/*++
+
+Routine Description:
+
+ EvtDeviceD0Entry event callback must perform any operations that are
+ necessary before the specified device is used. It will be called every
+ time the hardware needs to be (re-)initialized.
+
+ This function is not marked pageable because this function is in the
+ device power up path. When a function is marked pagable and the code
+ section is paged out, it will generate a page fault which could impact
+ the fast resume behavior because the client driver will have to wait
+ until the system drivers can service this page fault.
+
+ This function runs at PASSIVE_LEVEL, even though it is not paged. A
+ driver can optionally make this function pageable if DO_POWER_PAGABLE
+ is set. Even if DO_POWER_PAGABLE isn't set, this function still runs
+ at PASSIVE_LEVEL. In this case, though, the function absolutely must
+ not do anything that will cause a page fault.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+ PreviousState - Device power state which the device was in most recently.
+ If the device is being newly started, this will be
+ PowerDeviceUnspecified.
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ PDEVICE_CONTEXT pDeviceContext;
+ NTSTATUS status;
+
+ pDeviceContext = GetDeviceContext(Device);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,
+ "-->OsrFxEvtEvtDeviceD0Entry - coming from %s\n",
+ DbgDevicePowerString(PreviousState));
+
+ status = WdfIoTargetStart(WdfUsbTargetDeviceGetIoTarget(pDeviceContext->UsbDevice));
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--OsrFxEvtEvtDeviceD0Entry\n");
+
+ return status;
+}
+
+
+NTSTATUS
+OsrFxEvtDeviceD0Exit(
+ IN WDFDEVICE Device,
+ IN WDF_POWER_DEVICE_STATE TargetState
+ )
+/*++
+
+Routine Description:
+
+ This routine undoes anything done in EvtDeviceD0Entry. It is called
+ whenever the device leaves the D0 state, which happens when the device is
+ stopped, when it is removed, and when it is powered off.
+
+ The device is still in D0 when this callback is invoked, which means that
+ the driver can still touch hardware in this routine.
+
+
+ EvtDeviceD0Exit event callback must perform any operations that are
+ necessary before the specified device is moved out of the D0 state. If the
+ driver needs to save hardware state before the device is powered down, then
+ that should be done here.
+
+ This function runs at PASSIVE_LEVEL, though it is generally not paged. A
+ driver can optionally make this function pageable if DO_POWER_PAGABLE is set.
+
+ Even if DO_POWER_PAGABLE isn't set, this function still runs at
+ PASSIVE_LEVEL. In this case, though, the function absolutely must not do
+ anything that will cause a page fault.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+ TargetState - Device power state which the device will be put in once this
+ callback is complete.
+
+Return Value:
+
+ Success implies that the device can be used. Failure will result in the
+ device stack being torn down.
+
+--*/
+{
+ PDEVICE_CONTEXT pDeviceContext;
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,
+ "-->OsrFxEvtDeviceD0Exit - moving to %s\n",
+ DbgDevicePowerString(TargetState));
+
+ pDeviceContext = GetDeviceContext(Device);
+
+ WdfIoTargetStop(WdfUsbTargetDeviceGetIoTarget(pDeviceContext->UsbDevice),
+ WdfIoTargetCancelSentIo);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--OsrFxEvtDeviceD0Exit\n");
+
+ return STATUS_SUCCESS;
+}
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+PCHAR
+DbgDevicePowerString(
+ _In_ WDF_POWER_DEVICE_STATE Type
+ )
+/*++
+
+Updated Routine Description:
+ DbgDevicePowerString does not change in this stage of the function driver.
+
+--*/
+{
+ switch (Type)
+ {
+ case WdfPowerDeviceInvalid:
+ return "WdfPowerDeviceInvalid";
+ case WdfPowerDeviceD0:
+ return "WdfPowerDeviceD0";
+ case WdfPowerDeviceD1:
+ return "WdfPowerDeviceD1";
+ case WdfPowerDeviceD2:
+ return "WdfPowerDeviceD2";
+ case WdfPowerDeviceD3:
+ return "WdfPowerDeviceD3";
+ case WdfPowerDeviceD3Final:
+ return "WdfPowerDeviceD3Final";
+ case WdfPowerDevicePrepareForHibernation:
+ return "WdfPowerDevicePrepareForHibernation";
+ case WdfPowerDeviceMaximum:
+ return "WdfPowerDeviceMaximum";
+ default:
+ return "UnKnown Device Power State";
+ }
+}
+
+
diff --git a/usb/kmdf_enumswitches/sys/driver.c b/usb/kmdf_enumswitches/sys/driver.c
new file mode 100644
index 00000000..10586be3
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/driver.c
@@ -0,0 +1,188 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Driver.c
+
+Abstract:
+
+ Main module.
+
+ This driver is for Open System Resources USB-FX2 Learning Kit designed
+ and built by OSR specifically for use in teaching software developers how to write
+ drivers for USB devices.
+
+ The board supports a single configuration. The board automatically
+ detects the speed of the host controller, and supplies either the
+ high or full speed configuration based on the host controller's speed.
+
+ The firmware supports 3 endpoints:
+
+ Endpoint number 1 is used to indicate the state of the 8-switch
+ switch-pack on the OSR USB-FX2 board. A single byte representing
+ the switch state is sent (a) when the board is first stated,
+ (b) when the board resumes after selective-suspend,
+ (c) whenever the state of the switches is changed.
+
+ Endpoints 6 and 8 perform an internal loop-back function.
+ Data that is sent to the board at EP6 is returned to the host on EP8.
+
+ For further information on the endpoints, please refer to the spec
+ http://www.osronline.com/hardware/OSRFX2_32.pdf.
+
+ Vendor ID of the device is 0x4705 and Product ID is 0x210.
+
+Environment:
+
+ Kernel mode only
+
+--*/
+
+#include <osrusbfx2.h>
+#include "trace.h"
+
+//
+// The trace message header (.tmh) file must be included in a source file
+// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS
+// macro (defined in toaster.h). During the compilation, WPP scans the source
+// files for DoTraceMessage() calls and builds a .tmh file which stores a unique
+// data GUID for each message, the text resource string for each message,
+// and the data types of the variables passed in for each message. This file
+// is automatically generated and used during post-processing.
+//
+#include "driver.tmh"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, DriverEntry)
+#pragma alloc_text(PAGE, OsrFxEvtDriverContextCleanup)
+#endif
+
+NTSTATUS
+DriverEntry(
+ PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+ DriverEntry initializes the driver and is the first routine called by the
+ system after the driver is loaded.
+
+Parameters Description:
+
+ DriverObject - represents the instance of the function driver that is loaded
+ into memory. DriverEntry must initialize members of DriverObject before it
+ returns to the caller. DriverObject is allocated by the system before the
+ driver is loaded, and it is released by the system after the system unloads
+ the function driver from memory.
+
+ RegistryPath - represents the driver specific path in the Registry.
+ The function driver can use the path to store driver related data between
+ reboots. The path does not store hardware instance specific data.
+
+Return Value:
+
+ STATUS_SUCCESS if successful,
+ STATUS_UNSUCCESSFUL otherwise.
+
+--*/
+{
+ WDF_DRIVER_CONFIG config;
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES attributes;
+
+ //
+ // Initialize WPP Tracing
+ //
+ WPP_INIT_TRACING(DriverObject, RegistryPath);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "OSRUSBFX2 Driver Sample - Driver Framework Edition.\n");
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "Built %s %s\n", __DATE__, __TIME__);
+
+ //
+ // Initiialize driver config to control the attributes that
+ // are global to the driver. Note that framework by default
+ // provides a driver unload routine. If you create any resources
+ // in the DriverEntry and want to be cleaned in driver unload,
+ // you can override that by manually setting the EvtDriverUnload in the
+ // config structure. In general xxx_CONFIG_INIT macros are provided to
+ // initialize most commonly used members.
+ //
+
+ WDF_DRIVER_CONFIG_INIT(
+ &config,
+ OsrFxEvtDeviceAdd
+ );
+
+ //
+ // Register a cleanup callback so that we can call WPP_CLEANUP when
+ // the framework driver object is deleted during driver unload.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.EvtCleanupCallback = OsrFxEvtDriverContextCleanup;
+
+ //
+ // Create a framework driver object to represent our driver.
+ //
+ status = WdfDriverCreate(
+ DriverObject,
+ RegistryPath,
+ &attributes, // Driver Attributes
+ &config, // Driver Config Info
+ WDF_NO_HANDLE // hDriver
+ );
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
+ "WdfDriverCreate failed with status 0x%x\n", status);
+ //
+ // Cleanup tracing here because DriverContextCleanup will not be called
+ // as we have failed to create WDFDRIVER object itself.
+ // Please note that if your return failure from DriverEntry after the
+ // WDFDRIVER object is created successfully, you don't have to
+ // call WPP cleanup because in those cases DriverContextCleanup
+ // will be executed when the framework deletes the DriverObject.
+ //
+ WPP_CLEANUP(DriverObject);
+ }
+
+ return status;
+}
+
+VOID
+OsrFxEvtDriverContextCleanup(
+ IN WDFOBJECT Driver
+ )
+/*++
+Routine Description:
+
+ Free resources allocated in DriverEntry that are not
+ automatically cleaned up framework.
+
+Arguments:
+
+ Driver - handle to a WDF Driver object.
+
+Return Value:
+
+ VOID.
+
+--*/
+{
+ PAGED_CODE ();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,"<-- OsrFxEvtDriverContextCleanup\n");
+
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)Driver ));
+}
+
diff --git a/usb/kmdf_enumswitches/sys/interrupt.c b/usb/kmdf_enumswitches/sys/interrupt.c
new file mode 100644
index 00000000..bb84af8b
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/interrupt.c
@@ -0,0 +1,195 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Interrupt.c
+
+Abstract:
+
+ This modules has routines configure a continuous reader on an
+ interrupt pipe to asynchronously read toggle switch states.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include <osrusbfx2.h>
+
+#include "interrupt.tmh"
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+OsrFxConfigContReaderForInterruptEndPoint(
+ _In_ PDEVICE_CONTEXT DeviceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine configures a continuous reader on the
+ interrupt endpoint. It's called from the PrepareHarware event.
+
+Arguments:
+
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ WDF_USB_CONTINUOUS_READER_CONFIG contReaderConfig;
+ NTSTATUS status;
+ WDFUSBPIPE pipe;
+
+ pipe = WdfUsbInterfaceGetConfiguredPipe(DeviceContext->UsbInterface,
+ INTERRUPT_IN_ENDPOINT_INDEX, // PipeIndex,
+ NULL); // pipeInfo
+ //
+ // Tell the framework that it's okay to read less than
+ // MaximumPacketSize
+ //
+ WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe);
+
+ WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&contReaderConfig,
+ OsrFxEvtUsbInterruptPipeReadComplete,
+ DeviceContext, // Context
+ sizeof(UCHAR)); // TransferLength
+
+ contReaderConfig.EvtUsbTargetPipeReadersFailed =
+ OsrFxEvtUsbInterruptReadersFailed;
+
+ //
+ // 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 CONFIG macro.
+ //
+ status = WdfUsbTargetPipeConfigContinuousReader(pipe, &contReaderConfig);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "OsrFxConfigContReaderForInterruptEndPoint failed %x\n",
+ status);
+ return status;
+ }
+
+ return status;
+}
+
+VOID
+OsrFxEvtUsbInterruptPipeReadComplete(
+ WDFUSBPIPE Pipe,
+ WDFMEMORY Buffer,
+ size_t NumBytesTransferred,
+ WDFCONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This the completion routine of the continour reader. This can
+ called concurrently on multiprocessor system if there are
+ more than one readers configured. So make sure to protect
+ access to global resources.
+
+Arguments:
+
+ Buffer - This buffer is freed when this call returns.
+ If the driver wants to delay processing of the buffer, it
+ can take an additional referrence.
+
+ Context - Provided in the WDF_USB_CONTINUOUS_READER_CONFIG_INIT macro
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ PUCHAR switchState = NULL;
+ WDFDEVICE device;
+ PDEVICE_CONTEXT pDeviceContext = Context;
+
+ UNREFERENCED_PARAMETER(Pipe);
+
+ device = WdfObjectContextGetObject(pDeviceContext);
+
+ //
+ // 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_WARNING, DBG_INIT,
+ "OsrFxEvtUsbInterruptPipeReadComplete Zero length read "
+ "occured on the Interrupt Pipe's Continuous Reader\n"
+ );
+ return;
+ }
+
+ NT_ASSERT(NumBytesTransferred == sizeof(UCHAR));
+
+ switchState = WdfMemoryGetBuffer(Buffer, NULL);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "OsrFxEvtUsbInterruptPipeReadComplete SwitchState %x\n",
+ *switchState);
+
+ pDeviceContext->CurrentSwitchState = *switchState;
+
+ OsrFxEnumerateChildren(device);
+}
+
+BOOLEAN
+OsrFxEvtUsbInterruptReadersFailed(
+ WDFUSBPIPE Pipe,
+ NTSTATUS Status,
+ USBD_STATUS UsbdStatus
+ )
+/*++
+
+Routine Description:
+
+ EvtUsbTargetPipeReadersFailed is called to inform the driver that a
+ continuous reader has reported an error while processing a read request.
+
+Arguments:
+
+ Pipe - handle to a framework pipe object.
+ Status - NTSTATUS value that the pipe's I/O target returned.
+ UsbdStatus - USBD_STATUS-typed status value that the pipe's I/O target returned.
+
+Return Value:
+
+ If TRUE, causes the framework to reset the USB pipe and then
+ restart the continuous reader.
+ If FASLE, the framework does not reset the device or restart
+ the continuous reader.
+
+ If this event is not registered, framework default action is to reset
+ the pipe and restart the reader.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Pipe);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "OsrFxEvtUsbInterruptReadersFailed NTSTATUS 0x%x, UsbdStatus 0x%x\n",
+ Status, UsbdStatus);
+
+ return TRUE;
+}
+
+
diff --git a/usb/kmdf_enumswitches/sys/kmdf_enumswitches.inx b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.inx
new file mode 100644
index 00000000..adab710e
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.inx
@@ -0,0 +1,112 @@
+;/*++
+;
+;Copyright (c) Microsoft Corporation. All rights reserved.
+;
+; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+; PURPOSE.
+;
+;Module Name:
+;
+; OSRUSBFX2.INF
+;
+;Abstract:
+; Installation inf for OSR USB-FX2 Learning Kit
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=Sample
+ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171}
+Provider=%MSFT%
+DriverVer=03/20/2003,5.00.3788
+CatalogFile=KmdfSamples.cat
+
+
+; ================= Class section =====================
+
+[ClassInstall32]
+Addreg=SampleClassReg
+
+[SampleClassReg]
+HKR,,,0,%ClassName%
+HKR,,Icon,,-5
+
+
+; ================= Device section =====================
+
+[Manufacturer]
+%MfgName%=Microsoft,NT$ARCH$
+
+[Microsoft.NT$ARCH$]
+%USB\VID_045E&PID_930A.DeviceDesc%=kmdf_enumswitches.Dev, USB\VID_0547&PID_1002
+%Switch.DeviceDesc%=Switch.Dev, {6FDE7521-1B65-48ae-B628-80BE62016026}\OsrUsbFxRawPdo
+
+
+[kmdf_enumswitches.Dev.NT]
+CopyFiles=kmdf_enumswitches.Files.Ext
+
+[Switch.Dev.NT]
+;dummy section
+
+[Switch.Dev.NT.Services]
+AddService = , %SPSVCINST_ASSOCSERVICE%,
+
+[kmdf_enumswitches.Dev.NT.Services]
+AddService = kmdf_enumswitches, %SPSVCINST_ASSOCSERVICE%, kmdf_enumswitches.AddService
+
+[kmdf_enumswitches.AddService]
+DisplayName = %kmdf_enumswitches.SvcDesc%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %10%\System32\Drivers\kmdf_enumswitches.sys
+
+[kmdf_enumswitches.Files.Ext]
+kmdf_enumswitches.sys
+
+[SourceDisksNames]
+1=%Disk_Description%,,,
+
+[SourceDisksFiles]
+kmdf_enumswitches.sys = 1
+
+[DestinationDirs]
+DefaultDestDir = 12
+
+;-------------- WDF Coinstaller installation
+
+[DestinationDirs]
+CoInstaller_CopyFiles = 11
+
+[kmdf_enumswitches.Dev.NT.CoInstallers]
+AddReg=CoInstaller_AddReg
+CopyFiles=CoInstaller_CopyFiles
+
+[CoInstaller_CopyFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
+
+[SourceDisksFiles]
+WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
+
+[CoInstaller_AddReg]
+HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
+
+[kmdf_enumswitches.Dev.NT.Wdf]
+KmdfService = kmdf_enumswitches, kmdf_enumswitches_wdfsect
+[kmdf_enumswitches_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+;---------------------------------------------------------------;
+
+[Strings]
+MSFT="Microsoft"
+MfgName="OSR"
+Disk_Description="OSRUSBFX2 Installation Disk"
+USB\VID_045E&PID_930A.DeviceDesc="WDF Sample Bus Driver for OSR USB-FX2 Learning Kit"
+kmdf_enumswitches.SvcDesc="WDF Sample Bus Driver for OSR USB-FX2 Learning Kit"
+ClassName = "Sample Device"
+Switch.DeviceDesc = "OsrUsbFX2 RawPdo For Switch"
+SPSVCINST_ASSOCSERVICE= 0x00000002
diff --git a/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj
new file mode 100644
index 00000000..a8bde5c4
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj
@@ -0,0 +1,229 @@
+<?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>{6A32E70D-E961-4940-A1E8-AB1A7CED390D}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{5F18CAB2-2FE2-4E6B-BA36-C0EFF928BB0E}</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>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType>KMDF</DriverType>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</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="Driver.c; device.c; interrupt.c; rawpdo.c">
+ <WppEnabled>true</WppEnabled>
+ <WppKernelMode>true</WppKernelMode>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{km-WdfDefault.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ </ClCompile>
+ <Inf Include="kmdf_enumswitches.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\kmdf_enumswitches.inf</CopyOutput>
+ </Inf>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>kmdf_enumswitches</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>kmdf_enumswitches</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>kmdf_enumswitches</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>kmdf_enumswitches</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\ntstrsafe.lib;$(DDK_LIB_PATH)\wdmsec.lib</AdditionalDependencies>
+ </Link>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING</PreprocessorDefinitions>
+ </Midl>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </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/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj.Filters b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj.Filters
new file mode 100644
index 00000000..f230f871
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/kmdf_enumswitches.vcxproj.Filters
@@ -0,0 +1,43 @@
+<?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>{8CFB48AC-E2E0-495E-B587-5D803D866819}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{D29CD043-B947-42D0-8741-B8510E442021}</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>{5A199DB9-BFEF-42C9-A546-9AA11B9322FE}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{634C8B4D-FD4D-4D9D-9A2A-9A4C2E388164}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="device.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Driver.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="interrupt.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="rawpdo.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\kmdf_enumswitches.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include="kmdf_enumswitches.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/kmdf_enumswitches/sys/osrusbfx2.h b/usb/kmdf_enumswitches/sys/osrusbfx2.h
new file mode 100644
index 00000000..968069c7
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/osrusbfx2.h
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ private.h
+
+Abstract:
+
+ Contains structure definitions and function prototypes private to
+ the driver.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include <initguid.h>
+#include <ntddk.h>
+#include "usbdi.h"
+#include "usbdlib.h"
+#include "public.h"
+#include "driverspecs.h"
+#include <wdf.h>
+#include <wdfusb.h>
+#define NTSTRSAFE_LIB
+#include <ntstrsafe.h>
+
+#include "trace.h"
+
+#ifndef _PRIVATE_H
+#define _PRIVATE_H
+
+#define POOL_TAG (ULONG) 'FRSO'
+#define _DRIVER_NAME_ "OSRUSBFX2"
+
+#define TEST_BOARD_TRANSFER_BUFFER_SIZE (64*1024)
+#define DEVICE_DESC_LENGTH 256
+
+extern const __declspec(selectany) LONGLONG DEFAULT_CONTROL_TRANSFER_TIMEOUT = 5 * -1 * WDF_TIMEOUT_TO_SEC;
+
+//
+// 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
+
+//
+// Define the features that we can clear
+// and set on our device
+//
+#define USBFX2LK_FEATURE_EPSTALL 0x00
+#define USBFX2LK_FEATURE_WAKE 0x01
+
+//
+// Order of endpoints in the interface descriptor
+//
+#define INTERRUPT_IN_ENDPOINT_INDEX 0
+#define BULK_OUT_ENDPOINT_INDEX 1
+#define BULK_IN_ENDPOINT_INDEX 2
+
+//
+// A structure representing the instance information associated with
+// this particular device.
+//
+
+typedef struct _DEVICE_CONTEXT {
+
+ WDFUSBDEVICE UsbDevice;
+
+ WDFUSBINTERFACE UsbInterface;
+
+ UCHAR CurrentSwitchState;
+
+} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
+
+extern ULONG DebugLevel;
+
+
+DRIVER_INITIALIZE DriverEntry;
+
+EVT_WDF_OBJECT_CONTEXT_CLEANUP OsrFxEvtDriverContextCleanup;
+
+EVT_WDF_DRIVER_DEVICE_ADD OsrFxEvtDeviceAdd;
+
+EVT_WDF_DEVICE_PREPARE_HARDWARE OsrFxEvtDevicePrepareHardware;
+
+EVT_WDF_IO_QUEUE_IO_READ OsrFxEvtIoRead;
+
+EVT_WDF_IO_QUEUE_IO_WRITE OsrFxEvtIoWrite;
+
+EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL OsrFxEvtIoDeviceControl;
+
+EVT_WDF_REQUEST_COMPLETION_ROUTINE EvtRequestReadCompletionRoutine;
+
+EVT_WDF_REQUEST_COMPLETION_ROUTINE EvtRequestWriteCompletionRoutine;
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+ResetPipe(
+ _In_ WDFUSBPIPE Pipe
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+ResetDevice(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+SelectInterfaces(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+AbortPipes(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+ReenumerateDevice(
+ _In_ PDEVICE_CONTEXT DevContext
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+GetBarGraphState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _Out_ PBAR_GRAPH_STATE BarGraphState
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+SetBarGraphState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+GetSevenSegmentState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _Out_ PUCHAR SevenSegment
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+SetSevenSegmentState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _In_ PUCHAR SevenSegment
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+GetSwitchState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _In_ PSWITCH_STATE SwitchState
+ );
+
+_IRQL_requires_(DISPATCH_LEVEL)
+VOID
+OsrUsbIoctlGetInterruptMessage(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+OsrFxSetPowerPolicy(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+OsrFxConfigContReaderForInterruptEndPoint(
+ _In_ PDEVICE_CONTEXT DeviceContext
+ );
+
+EVT_WDF_USB_READER_COMPLETION_ROUTINE OsrFxEvtUsbInterruptPipeReadComplete;
+
+EVT_WDF_USB_READERS_FAILED OsrFxEvtUsbInterruptReadersFailed;
+
+EVT_WDF_IO_QUEUE_IO_STOP OsrFxEvtIoStop;
+
+EVT_WDF_DEVICE_D0_ENTRY OsrFxEvtDeviceD0Entry;
+
+EVT_WDF_DEVICE_D0_EXIT OsrFxEvtDeviceD0Exit;
+
+_IRQL_requires_(PASSIVE_LEVEL)
+BOOLEAN
+OsrFxReadFdoRegistryKeyValue(
+ _In_ PWDFDEVICE_INIT DeviceInit,
+ _In_ PWCHAR Name,
+ _Out_ PULONG Value
+ );
+
+_IRQL_requires_max_(DISPATCH_LEVEL)
+VOID
+OsrFxEnumerateChildren(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+PCHAR
+DbgDevicePowerString(
+ _In_ WDF_POWER_DEVICE_STATE Type
+ );
+
+#endif
+
+
diff --git a/usb/kmdf_enumswitches/sys/rawpdo.c b/usb/kmdf_enumswitches/sys/rawpdo.c
new file mode 100644
index 00000000..2feb04e5
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/rawpdo.c
@@ -0,0 +1,330 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Rawpdo.c
+
+Abstract:
+
+ This modules has routines to enumerate dip switches on the board
+ as child devices. We use dynamic enumeration interfaces to manage
+ child devices.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include <osrusbfx2.h>
+#include "rawpdo.h"
+
+#include "rawpdo.tmh"
+
+VOID
+OsrFxInitChildList(
+ IN PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+
+Routine Description:
+
+ This routine is called from the EvtDeviceAdd routine to initialize
+ the default child list.
+
+Arguments:
+
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ WDF_CHILD_LIST_CONFIG config;
+
+ //
+ // Init the default child list so that we can enumerate a raw PDO
+ //
+ WDF_CHILD_LIST_CONFIG_INIT(&config,
+ sizeof(PDO_IDENTIFICATION_DESCRIPTION),
+ OsrEvtDeviceListCreatePdo // callback to create a child device.
+ );
+ //
+ // Tell the framework to use the built-in devicelist to track the state
+ // of the device based on the configuration we just created.
+ //
+ WdfFdoInitSetDefaultChildListConfig(DeviceInit,
+ &config,
+ WDF_NO_OBJECT_ATTRIBUTES);
+
+ return;
+
+}
+
+
+NTSTATUS
+OsrEvtDeviceListCreatePdo(
+ WDFCHILDLIST DeviceList,
+ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
+ PWDFDEVICE_INIT ChildInit
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework in response to Query-Device relation when
+ a new PDO for a child device needs to be created.
+
+Arguments:
+
+ DeviceList - Handle to the default WDFCHILDLIST created by the
+ framework as part of FDO.
+
+ IdentificationDescription - Decription of the new child device.
+
+ ChildInit - It's a opaque structure used in collecting device settings
+ and passed in as a parameter to CreateDevice.
+
+Return Value:
+
+ NT Status code.
+
+--*/
+{
+ NTSTATUS status;
+ WDFDEVICE hChild = NULL;
+ PPDO_IDENTIFICATION_DESCRIPTION pDesc;
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
+ DECLARE_CONST_UNICODE_STRING(deviceId, OSRUSBFX2_SWITCH_DEVICE_ID );
+ DECLARE_CONST_UNICODE_STRING(hardwareId, OSRUSBFX2_SWITCH_DEVICE_ID );
+ DECLARE_CONST_UNICODE_STRING(deviceLocation, L"OSR USB-FX2 Learning Kit" );
+ DECLARE_UNICODE_STRING_SIZE(buffer, DEVICE_DESC_LENGTH);
+
+ UNREFERENCED_PARAMETER(DeviceList);
+
+ pDesc = CONTAINING_RECORD(IdentificationDescription,
+ PDO_IDENTIFICATION_DESCRIPTION,
+ Header);
+
+ //
+ // Mark the device RAW so that the child device can be started
+ // and accessed without requiring a function driver. Since we are
+ // creating a RAW PDO, we must provide a class guid.
+ //
+ status = WdfPdoInitAssignRawDevice(ChildInit, &GUID_DEVCLASS_OSRUSBFX2);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+ }
+
+ //
+ // Since our devices for switches can trigger nuclear explosion,
+ // we must protect them from random users sending I/Os.
+ //
+ status = WdfDeviceInitAssignSDDLString(ChildInit,
+ &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+ }
+
+ status = WdfPdoInitAssignDeviceID(ChildInit, &deviceId);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+ }
+
+ //
+ // On XP and later, there is no need to provide following IDs for raw pdos.
+ // BusQueryHardwareIDs but on On Win2K, we must provide a HWID and a NULL
+ // section in the INF to get the device installed without any problem.
+ //
+ status = WdfPdoInitAddHardwareID(ChildInit, &hardwareId);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+ }
+
+ //
+ // Since we are enumerating more than one children, we must
+ // provide a BusQueryInstanceID. If we don't, system will throw
+ // CA bugcheck.
+ //
+ status = RtlUnicodeStringPrintf(&buffer, L"%02d", pDesc->SwitchNumber);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ //
+ // Provide a description about the device. This text is usually read from
+ // the device. In the case of USB device, this text comes from the string
+ // descriptor. This text is displayed momentarily by the PnP manager while
+ // it's looking for a matching INF. If it finds one, it uses the Device
+ // Description from the INF file to display in the device manager.
+ // Since our device is raw device and we don't provide any hardware ID
+ // to match with an INF, this text will be displayed in the device manager.
+ //
+ status = RtlUnicodeStringPrintf(&buffer,
+ L"OsrUsbFX2 RawPdo For Switch %02d",
+ pDesc->SwitchNumber);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+ }
+
+ //
+ // You can call WdfPdoInitAddDeviceText multiple times, adding device
+ // text for multiple locales. When the system displays the text, it
+ // chooses the text that matches the current locale, if available.
+ // Otherwise it will use the string for the default locale.
+ // The driver can specify the driver's default locale by calling
+ // WdfPdoInitSetDefaultLocale.
+ //
+ status = WdfPdoInitAddDeviceText(ChildInit,
+ &buffer,
+ &deviceLocation,
+ 0x409);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+ }
+
+ WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
+
+ status = WdfDeviceCreate(&ChildInit, WDF_NO_OBJECT_ATTRIBUTES, &hChild);
+ if (!NT_SUCCESS(status)) {
+ goto Cleanup;
+
+ }
+
+ //
+ // Set idle-time out on the child device. This is required to allow
+ // the parent device to idle-out when there are no active I/O.
+ //
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0);
+ idleSettings.IdleTimeout = 1000; // 1-sec
+
+ status = WdfDeviceAssignS0IdleSettings(hChild, &idleSettings);
+ if ( !NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);
+ return status;
+ }
+
+ return status;
+
+Cleanup:
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"CreatePdo failed %x\n", status);
+
+ //
+ // On error, framework will cleanup all the resources when it deletes
+ // the device. So there is nothing to do.
+ //
+
+ return status;
+}
+
+_IRQL_requires_max_(DISPATCH_LEVEL)
+VOID
+OsrFxEnumerateChildren(
+ _In_ WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ This routine configures a continuous reader on the
+ interrupt endpoint.
+
+Arguments:
+
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ WDFCHILDLIST list;
+ UCHAR i;
+ NTSTATUS status;
+ PDEVICE_CONTEXT pDeviceContext;
+
+ pDeviceContext = GetDeviceContext(Device);
+
+ list = WdfFdoGetDefaultChildList(Device);
+
+ WdfChildListBeginScan(list);
+
+ //
+ // A call to WdfChildListBeginScan indicates to the framework that the
+ // driver is about to scan for dynamic children. If the driver doesn't
+ // call either WdfChildListUpdateChildDescriptionAsPresent or
+ // WdfChildListMarkAllChildDescriptionsPresent before WdfChildListEndScan is,
+ // called, all the previously reported children will be reported as missing
+ // to the PnP subsystem.
+ //
+ for(i=0; i< RTL_BITS_OF(UCHAR); i++) {
+
+ //
+ // Report every set bit in the switchstate as a child device.
+ //
+ if(pDeviceContext->CurrentSwitchState & (1<<i)) {
+
+ PDO_IDENTIFICATION_DESCRIPTION description;
+
+ //
+ // Initialize the description with the information about the newly
+ // plugged in device.
+ //
+ WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(
+ &description.Header,
+ sizeof(description)
+ );
+
+ //
+ // Since switches are marked in the wrong order on the board,
+ // we will fix it here so that the DM display matches with the
+ // board.
+ //
+ description.SwitchNumber = RTL_BITS_OF(UCHAR)-i;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "Switch %d is ON\n", description.SwitchNumber);
+
+ //
+ // Call the framework to add this child to the devicelist. This call
+ // will internaly call our DescriptionCompare callback to check
+ // whether this device is a new device or existing device. If
+ // it's a new device, the framework will call DescriptionDuplicate to create
+ // a copy of this description in nonpaged pool.
+ // The actual creation of the child device will happen when the framework
+ // receives QUERY_DEVICE_RELATION request from the PNP manager in
+ // response to InvalidateDevice relation call made as part of adding
+ // a new child.
+ //
+ status = WdfChildListAddOrUpdateChildDescriptionAsPresent(
+ list,
+ &description.Header,
+ NULL); // AddressDescription
+
+ if (status == STATUS_OBJECT_NAME_EXISTS) {
+ }
+
+ }
+ }
+
+
+ WdfChildListEndScan(list);
+
+ return;
+}
+
diff --git a/usb/kmdf_enumswitches/sys/rawpdo.h b/usb/kmdf_enumswitches/sys/rawpdo.h
new file mode 100644
index 00000000..66eab3e1
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/rawpdo.h
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Rawpdo.h
+
+Abstract:
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#ifndef _RAWPDO_H
+#define _RAWPDO_H
+
+#ifndef RTL_BITS_OF
+// This macro is not defined in Win2k ntdef.h
+#define RTL_BITS_OF(sizeOfArg) (sizeof(sizeOfArg) * 8)
+#endif
+
+//
+// Used to identify kbfilter bus. This guid is used as the enumeration string
+// for the device id.
+DEFINE_GUID(GUID_BUS_OSRUSBFX2_RAWPDO,
+0x556cf9d3, 0xe853, 0x4dfb, 0xa2, 0x16, 0x5d, 0x75, 0x6d, 0xf2, 0xc1, 0x7a);
+// {556CF9D3-E853-4dfb-A216-5D756DF2C17A}
+
+
+DEFINE_GUID(GUID_DEVCLASS_OSRUSBFX2,
+0x6fde7521, 0x1b65, 0x48ae, 0xb6, 0x28, 0x80, 0xbe, 0x62, 0x1, 0x60, 0x26);
+// {6FDE7521-1B65-48ae-B628-80BE62016026}
+
+// \0 in the end is for double termination - required for MULTI_SZ string
+#define OSRUSBFX2_SWITCH_DEVICE_ID L"{6FDE7521-1B65-48ae-B628-80BE62016026}\\OsrUsbFxRawPdo\0"
+
+typedef struct _PDO_IDENTIFICATION_DESCRIPTION
+{
+ WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header; // should contain this header
+
+ ULONG SwitchNumber;
+
+} PDO_IDENTIFICATION_DESCRIPTION, *PPDO_IDENTIFICATION_DESCRIPTION;
+
+VOID
+OsrFxInitChildList(
+ IN PWDFDEVICE_INIT DeviceInit
+ );
+
+EVT_WDF_CHILD_LIST_CREATE_DEVICE OsrEvtDeviceListCreatePdo;
+
+#endif
diff --git a/usb/kmdf_enumswitches/sys/trace.h b/usb/kmdf_enumswitches/sys/trace.h
new file mode 100644
index 00000000..518ff5f1
--- /dev/null
+++ b/usb/kmdf_enumswitches/sys/trace.h
@@ -0,0 +1,115 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ TRACE.h
+
+Abstract:
+
+ Header file for the debug tracing related function defintions and macros.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include <evntrace.h> // For TRACE_LEVEL definitions
+
+#if !defined(EVENT_TRACING)
+
+//
+// TODO: These defines are missing in evntrace.h
+// in some DDK build environments (XP).
+//
+#if !defined(TRACE_LEVEL_NONE)
+ #define TRACE_LEVEL_NONE 0
+ #define TRACE_LEVEL_CRITICAL 1
+ #define TRACE_LEVEL_FATAL 1
+ #define TRACE_LEVEL_ERROR 2
+ #define TRACE_LEVEL_WARNING 3
+ #define TRACE_LEVEL_INFORMATION 4
+ #define TRACE_LEVEL_VERBOSE 5
+ #define TRACE_LEVEL_RESERVED6 6
+ #define TRACE_LEVEL_RESERVED7 7
+ #define TRACE_LEVEL_RESERVED8 8
+ #define TRACE_LEVEL_RESERVED9 9
+#endif
+
+
+//
+// Define Debug Flags
+//
+#define DBG_INIT 0x00000001
+#define DBG_PNP 0x00000002
+#define DBG_POWER 0x00000004
+#define DBG_WMI 0x00000008
+#define DBG_CREATE_CLOSE 0x00000010
+#define DBG_IOCTL 0x00000020
+#define DBG_WRITE 0x00000040
+#define DBG_READ 0x00000080
+
+
+VOID
+TraceEvents (
+ _In_ ULONG DebugPrintLevel,
+ _In_ ULONG DebugPrintFlag,
+ _Printf_format_string_
+ _In_ PCSTR DebugMessage,
+ ...
+ );
+
+#define WPP_INIT_TRACING(DriverObject, RegistryPath)
+#define WPP_CLEANUP(DriverObject)
+
+#else
+//
+// If software tracing is defined in the sources file..
+// WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver.
+// *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID ***
+// WPP_DEFINE_BIT allows setting debug bit masks to selectively print.
+// The names defined in the WPP_DEFINE_BIT call define the actual names
+// that are used to control the level of tracing for the control guid
+// specified.
+//
+// NOTE: If you are adopting this sample for your driver, please generate
+// a new guid, using tools\other\i386\guidgen.exe present in the
+// DDK.
+//
+// Name of the logger is OSRUSBFX2 and the guid is
+// {D23A0C5A-D307-4f0e-AE8E-E2A355AD5DAB}
+// (0xd23a0c5a, 0xd307, 0x4f0e, 0xae, 0x8e, 0xe2, 0xa3, 0x55, 0xad, 0x5d, 0xab);
+//
+
+#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID(OsrUsbFxTraceGuid,(d23a0c5a,d307,4f0e,ae8e,E2A355AD5DAB), \
+ WPP_DEFINE_BIT(DBG_INIT) /* bit 0 = 0x00000001 */ \
+ WPP_DEFINE_BIT(DBG_PNP) /* bit 1 = 0x00000002 */ \
+ WPP_DEFINE_BIT(DBG_POWER) /* bit 2 = 0x00000004 */ \
+ WPP_DEFINE_BIT(DBG_WMI) /* bit 3 = 0x00000008 */ \
+ WPP_DEFINE_BIT(DBG_CREATE_CLOSE) /* bit 4 = 0x00000010 */ \
+ WPP_DEFINE_BIT(DBG_IOCTL) /* bit 5 = 0x00000020 */ \
+ WPP_DEFINE_BIT(DBG_WRITE) /* bit 6 = 0x00000040 */ \
+ WPP_DEFINE_BIT(DBG_READ) /* bit 7 = 0x00000080 */ \
+ /* You can have up to 32 defines. If you want more than that,\
+ you have to provide another trace control GUID */\
+ )
+
+
+#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)
+
+
+#endif
+
+
+