summaryrefslogtreecommitdiff
path: root/usb/umdf2_fx2
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/umdf2_fx2
parentef1905bf1e8825bb31120dfb27e0daf3154d859a (diff)
Initial publish
Diffstat (limited to 'usb/umdf2_fx2')
-rw-r--r--usb/umdf2_fx2/ReadMe.md326
-rw-r--r--usb/umdf2_fx2/deviceMetadata/B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-msbin0 -> 105893 bytes
-rw-r--r--usb/umdf2_fx2/driver/Device.c911
-rw-r--r--usb/umdf2_fx2/driver/bulkrwr.c430
-rw-r--r--usb/umdf2_fx2/driver/driver.c277
-rw-r--r--usb/umdf2_fx2/driver/interrupt.c184
-rw-r--r--usb/umdf2_fx2/driver/ioctl.c1056
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2.h312
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2.man309
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2.rc13
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2um.inx103
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2um.vcxproj216
-rw-r--r--usb/umdf2_fx2/driver/osrusbfx2um.vcxproj.Filters51
-rw-r--r--usb/umdf2_fx2/driver/trace.h115
-rw-r--r--usb/umdf2_fx2/exe/dump.c444
-rw-r--r--usb/umdf2_fx2/exe/osrusbfx2.vcxproj181
-rw-r--r--usb/umdf2_fx2/exe/osrusbfx2.vcxproj.Filters30
-rw-r--r--usb/umdf2_fx2/exe/test.cmd6
-rw-r--r--usb/umdf2_fx2/exe/testapp.c1262
-rw-r--r--usb/umdf2_fx2/exe/testapp.rc12
-rw-r--r--usb/umdf2_fx2/inc/prototypes.h14
-rw-r--r--usb/umdf2_fx2/inc/public.h173
-rw-r--r--usb/umdf2_fx2/umdf2_fx2.sln46
23 files changed, 6471 insertions, 0 deletions
diff --git a/usb/umdf2_fx2/ReadMe.md b/usb/umdf2_fx2/ReadMe.md
new file mode 100644
index 00000000..74e1885e
--- /dev/null
+++ b/usb/umdf2_fx2/ReadMe.md
@@ -0,0 +1,326 @@
+Sample UMDF Function Driver for OSR USB-FX2 (UMDF Version 1)
+============================================================
+
+The umdf\_fx2 sample is a User-Mode Driver Framework (UMDF) driver for the OSR USB-FX2 device. It includes a test app and sample device metadata, and supports impersonation and idle power down.
+
+## Universal Compliant
+This sample builds a Windows Universal driver. It uses only APIs and DDIs that are included in Windows Core.
+
+The sample can also be used with the CustomDeviceAccess MSDK sample. The sample demonstrates how to perform bulk and interrupt data transfers to an USB device. The specification for the device is at <http://www.osronline.com/hardware/OSRFX2_32.pdf>. The driver and sample device metadata also work with the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample.
+
+Starting in Windows 8.1, the osrusbfx2 sample has been divided into these samples:
+
+- [WDF Sample Driver Learning Lab for OSR USB-FX2](http://msdn.microsoft.com/en-us/library/windows/hardware/): This sample is a series of iterative drivers that demonstrate how to write a "Hello World" driver and adds additional features in each step.
+
+- [kmdf\_fx2](gallery_samples.123a_gallery#1): This sample is the final version of kernel-mode [wdf\_osrfx2](http://msdn.microsoft.com/en-us/library/windows/hardware/) driver. The sample demonstrates KMDF methods.
+
+- umdf\_fx2: This sample is the final version of the user-mode driver [wdf\_osrfx2](http://msdn.microsoft.com/en-us/library/windows/hardware/). The sample demonstrates UMDF methods.
+
+Overview
+--------
+
+Here is the overview of the device:
+
+- The device is based on the development board supplied with the Cypress EZ-USB FX2 Development Kit (CY3681).
+- It contains 1 interface and 3 endpoints (Interrupt IN, Bulk Out, Bulk IN).
+- Firmware supports vendor commands to query or set LED Bar graph display and 7-segment LED display, and to 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 (for example, bit 0x80 is labeled 1 on the pack).
+- Bulk Endpoints are configured for loopback:
+ - The device moves data from IN endpoint to OUT endpoint.
+ - The 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).
+
+Testing the driver
+------------------
+
+You can use the [Custom driver access](http://go.microsoft.com/fwlink/p/?LinkID=248288) sample to test the umdf\_fx2 sample.
+
+This sample also includes a test application, osrusbfx2.exe, that you can use to test the device. This console application enumerates the interface registered by the driver and opens the device to send read, write, or IOCTL requests based on the command line options.
+
+Usage for Read/Write test:
+
+- -r [*n*], where *n* is number of bytes to read.
+- -w [*n*], where *n* is number of bytes to write.
+- -c [*n*], where *n* is number of iterations (default = 1).
+- -v, shows verbose read data.
+- -p, plays with Bar Display, Dip Switch, 7-Segment Display.
+- -a, performs asynchronous I/O operation.
+- -u, dumps USB configuration and pipe information.
+- -f \<*filename*\> [*interval-seconds*], where *interval-seconds* is a delay in milliseconds, to send a text file to the seven-segment display (UMDF only)
+
+**Playing with the 7 segment display, toggle switches, and bar graph display**
+
+Use the command **osrusbfx2.exe -p** with options 1 through 9 to set and clear bar graph display, set and get 7 segment state, and read the toggle switch states. The following shows the function options:
+
+1. Light Bar
+2. Clear Bar
+3. Light entire Bar graph
+4. Clear entire Bar graph
+5. Get bar graph state
+6. Get Switch state
+7. Get Switch Interrupt Message
+8. Get 7 segment state
+9. Set 7 segment state
+10. Reset the device
+11. Re-enumerate the device
+
+0. Exit
+
+Selection:
+
+**Reset and re-enumerate the device**
+
+Use the command **osrusbfx2.exe -p** with options 10 and 11 to either reset the device or re-enumerate the device.
+
+**Read and write to bulk endpoints**
+
+The following commands send read and write requests to the device's bulk endpoint.
+
+- `osrusbfx2.exe -r 64`
+
+ The preceding command reads 64 bytes to the bulk IN endpoint.
+
+- `osrusbfx2.exe -w 64 `
+
+ The preceding command writes 64 bytes to the bulk OUT endpoint.
+
+- `osrusbfx2.exe -r 64 -w 64 -c 100 -v`
+
+ The preceding command first writes 64 bytes of data to bulk OUT endpoint (Pipe 1), then reads 64 bytes from bulk IN endpoint (Pipe 2), and then compares the read buffer with write buffer to see if they match. If the buffer contents match, it repeats this operation 100 times.
+
+- `osrusbfx2.exe -a`
+
+ The preceding command reads and writes to the device asynchronously in an infinite loop.
+
+The bulk endpoints are double buffered. Depending on the operational speed (full or high), the buffer size is either 64 bytes or 512 bytes, respectively. A request to read data does not complete if the buffers are empty. If the buffers are full, a request to write data does not complete until the buffers are emptied. When you are doing a synchronous read, make sure the endpoint buffer has data (for example, when you send 512 bytes write request to the device operating in full speed mode). Because the endpoints are double buffered, the total buffer capacity is 256 bytes. The first 256 bytes fills the buffer and the write request waits in the USB stack until the buffers are emptied. If you run another instance of the application to read 512 bytes of data, both write and read requests complete successfully.
+
+**Displaying descriptors**
+
+The following command displays all the descriptors and endpoint information.
+
+**osrusbfx2.exe -u**
+
+If the device is operating in high speed mode, you get the following information:
+
+`===================`
+
+`USB_CONFIGURATION_DESCRIPTOR`
+
+`bLength = 0x9, decimal 9`
+
+`bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )`
+
+`wTotalLength = 0x27, decimal 39`
+
+`bNumInterfaces = 0x1, decimal 1`
+
+`bConfigurationValue = 0x1, decimal 1`
+
+`iConfiguration = 0x4, decimal 4`
+
+`bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )`
+
+`MaxPower = 0x32, decimal 50`
+
+`-----------------------------`
+
+`USB_INTERFACE_DESCRIPTOR #0`
+
+`bLength = 0x9`
+
+`bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )`
+
+`bInterfaceNumber = 0x0`
+
+`bAlternateSetting = 0x0`
+
+`bNumEndpoints = 0x3`
+
+`bInterfaceClass = 0xff`
+
+`bInterfaceSubClass = 0x0`
+
+`bInterfaceProtocol = 0x0`
+
+`bInterface = 0x0`
+
+`------------------------------`
+
+`USB_ENDPOINT_DESCRIPTOR for Pipe00`
+
+`bLength = 0x7`
+
+`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+
+`bEndpointAddress= 0x81 ( INPUT )`
+
+`bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )`
+
+`wMaxPacketSize= 0x49, decimal 73`
+
+`bInterval = 0x1, decimal 1`
+
+`------------------------------`
+
+`USB_ENDPOINT_DESCRIPTOR for Pipe01`
+
+`bLength = 0x7`
+
+`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+
+`bEndpointAddress= 0x6 ( OUTPUT )`
+
+`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+
+`wMaxPacketSize= 0x200, `
+
+`decimal 512 bInterval = 0x0, `
+
+`decimal 0`
+
+`------------------------------`
+
+`USB_ENDPOINT_DESCRIPTOR for Pipe02`
+
+`bLength = 0x7`
+
+`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+
+`bEndpointAddress= 0x88 ( INPUT )`
+
+`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+
+`wMaxPacketSize= 0x200, decimal 512`
+
+`bInterval = 0x0, decimal 0`
+
+If the device is operating in low speed mode, you will get the following information:
+
+`===================`
+
+`USB_CONFIGURATION_DESCRIPTOR`
+
+`bLength = 0x9, decimal 9`
+
+`bDescriptorType = 0x2 ( USB_CONFIGURATION_DESCRIPTOR_TYPE )`
+
+`wTotalLength = 0x27, decimal 39`
+
+`bNumInterfaces = 0x1, decimal 1`
+
+`bConfigurationValue = 0x1, decimal 1`
+
+`iConfiguration = 0x3, decimal 3`
+
+`bmAttributes = 0xa0 ( USB_CONFIG_BUS_POWERED )`
+
+`MaxPower = 0x32, decimal 50 `
+
+`-----------------------------`
+
+`USB_INTERFACE_DESCRIPTOR #0`
+
+`bLength = 0x9`
+
+`bDescriptorType = 0x4 ( USB_INTERFACE_DESCRIPTOR_TYPE )`
+
+`bInterfaceNumber = 0x0 bAlternateSetting = 0x0`
+
+`bNumEndpoints = 0x3`
+
+`bInterfaceClass = 0xff`
+
+`bInterfaceSubClass = 0x0`
+
+`bInterfaceProtocol = 0x0`
+
+`bInterface = 0x0`
+
+`------------------------------`
+
+`USB_ENDPOINT_DESCRIPTOR for Pipe00`
+
+`bLength = 0x7`
+
+`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+
+`bEndpointAddress= 0x81 ( INPUT )`
+
+`bmAttributes= 0x3 ( USB_ENDPOINT_TYPE_INTERRUPT )`
+
+`wMaxPacketSize= 0x49, decimal 73`
+
+`bInterval = 0x1, decimal 1`
+
+`------- -----------------------`
+
+`USB_ENDPOINT_DESCRIPTOR for Pipe01`
+
+`bLength = 0x7`
+
+`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+
+`bEndpointAddress= 0x6 ( OUTPUT )`
+
+`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+
+`wMaxPacketSize= 0x40, decimal 64`
+
+`bInterval = 0x0, decimal 0`
+
+`------------------------------`
+
+`USB_ENDPOINT_DESCRIPTOR for Pipe02`
+
+`bLength = 0x7`
+
+`bDescriptorType = 0x5 ( USB_ENDPOINT_DESCRIPTOR_TYPE )`
+
+`bEndpointAddress= 0x88 ( INPUT )`
+
+`bmAttributes= 0x2 ( USB_ENDPOINT_TYPE_BULK )`
+
+`wMaxPacketSize= 0x40, decimal 64`
+
+`bInterval = 0x0, decimal 0 `
+
+Sample Contents
+---------------
+
+Folder
+
+Description
+
+usb\\umdf\_fx2\\driver
+
+This directory contains driver code that demonstrates the following functionality:
+
+- Loads the driver and responds to PnP and Power events. You can install, uninstall, disable, enable, suspend, and resume the system.
+- Registers a PnP device interface so that application can open a handle to the device.
+- Implements **IPnpCallbackHardware** interface and initializes USB I/O targets in **IPnpCallbackHardware::OnPrepareHardware** method.
+- Creates a sequential queue for handling IOCTL requests.
+- Adds code to handle the IOCTL to set bar graph display.
+- Creates a parallel queue for handling read and write requests.
+- Retrieves memory from read and write requests, format the requests, and sends them to a USB target.
+- Supports additional IOCTLs to get and set the 7-segment display, get bar graph display, and get config descriptor.
+- Sets power policy for the device.
+- Adds code to indicate that the device is ready by lighting up the period on 7-segment display.
+- Calls **SetupDi** functions to determine the "BusTypeGUID" of the device, and uses impersonation to access resources that only the caller has access to.
+- Shows how to implement idle and wake functionality to make the driver the power policy owner (PPO). The sample achieves this using power-managed queues and UMDF DDIs, AssignS0IdleSettings, and AssignSxWakeSettings.
+- Demonstrates implementation of a continuous reader.
+- Demonstrates the use of impersonation.
+
+usb\\umdf\_fx2\\exe
+
+This directory contains a test application that can be used to drive the UMDF driver and FX2 device. This is a modified version of the test application for the KMDF Fx2 driver.
+
+usb\\umdf\_fx2\\deviceMetadata
+
+This directory contains the device metadata package for the sample. You must copy the device metadata to the system before installing the device. For information on how to update and deploy device metadata, see [Custom driver access sample](http://go.microsoft.com/fwlink/p/?LinkID=248288).
+
diff --git a/usb/umdf2_fx2/deviceMetadata/B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-ms b/usb/umdf2_fx2/deviceMetadata/B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-ms
new file mode 100644
index 00000000..5f8e82ee
--- /dev/null
+++ b/usb/umdf2_fx2/deviceMetadata/B4D697F5-1C56-4807-ACCD-B28C09D37FF0.devicemetadata-ms
Binary files differ
diff --git a/usb/umdf2_fx2/driver/Device.c b/usb/umdf2_fx2/driver/Device.c
new file mode 100644
index 00000000..0003dad7
--- /dev/null
+++ b/usb/umdf2_fx2/driver/Device.c
@@ -0,0 +1,911 @@
+/*++
+
+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:
+
+ User mode only
+
+
+--*/
+
+#include <osrusbfx2.h>
+#include <devpkey.h>
+
+#if defined(EVENT_TRACING)
+#include "device.tmh"
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, OsrFxEvtDeviceAdd)
+#pragma alloc_text(PAGE, OsrFxEvtDevicePrepareHardware)
+#pragma alloc_text(PAGE, OsrFxEvtDeviceD0Exit)
+#pragma alloc_text(PAGE, SelectInterfaces)
+#pragma alloc_text(PAGE, OsrFxSetPowerPolicy)
+#pragma alloc_text(PAGE, OsrFxReadFdoRegistryKeyValue)
+#pragma alloc_text(PAGE, GetDeviceEventLoggingNames)
+#endif
+
+
+NTSTATUS
+OsrFxEvtDeviceAdd(
+ WDFDRIVER Driver,
+ 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;
+ WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
+ WDF_IO_QUEUE_CONFIG ioQueueConfig;
+ PDEVICE_CONTEXT pDevContext;
+ WDFQUEUE queue;
+ GUID activity;
+
+ 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 wdfusb pipe continuous reader
+ // as we go in and out of the D0-working state.
+ //
+
+ pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;
+ pnpPowerCallbacks.EvtDeviceD0Exit = OsrFxEvtDeviceD0Exit;
+ pnpPowerCallbacks.EvtDeviceSelfManagedIoFlush = OsrFxEvtDeviceSelfManagedIoFlush;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
+
+ //
+ // 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;
+ }
+
+ //
+ // Setup the activity ID so that we can log events using it.
+ //
+
+ activity = DeviceToActivityId(device);
+
+ //
+ // Get the DeviceObject context by using accessor function specified in
+ // the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME macro for DEVICE_CONTEXT.
+ //
+ pDevContext = GetDeviceContext(device);
+
+ //
+ // Get the device's friendly name and location so that we can use it in
+ // error logging. If this fails then it will setup dummy strings.
+ //
+
+ GetDeviceEventLoggingNames(device);
+
+ //
+ // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
+ // that you don't get the popup in usermodewhen you surprise remove the device.
+ //
+ WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
+ pnpCaps.SurpriseRemovalOK = WdfTrue;
+
+ WdfDeviceSetPnpCapabilities(device, &pnpCaps);
+
+ //
+ // Create a parallel default queue and register an event callback to
+ // receive ioctl requests. We will create separate queues for
+ // handling read and write requests. All other requests will be
+ // completed with error status automatically by the framework.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
+ WdfIoQueueDispatchParallel);
+
+ ioQueueConfig.EvtIoDeviceControl = OsrFxEvtIoDeviceControl;
+
+ //
+ // By default, Static Driver Verifier (SDV) displays a warning if it
+ // doesn't find the EvtIoStop callback on a power-managed queue.
+ // The 'assume' below causes SDV to suppress this warning. If the driver
+ // has not explicitly set PowerManaged to WdfFalse, the framework creates
+ // power-managed queues when the device is not a filter driver. Normally
+ // the EvtIoStop is required for power-managed queues, but for this driver
+ // it is not needed b/c the driver doesn't hold on to the requests for
+ // long time or forward them to other drivers.
+ // If the EvtIoStop callback is not implemented, the framework waits for
+ // all driver-owned requests to be done before moving in the Dx/sleep
+ // states or before removing the device, which is the correct behavior
+ // for this type of driver. If the requests were taking an indeterminate
+ // amount of time to complete, or if the driver forwarded the requests
+ // to a lower driver/another stack, the queue should have an
+ // EvtIoStop/EvtIoResume.
+ //
+ __analysis_assume(ioQueueConfig.EvtIoStop != 0);
+ status = WdfIoQueueCreate(device,
+ &ioQueueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &queue);// pointer to default queue
+ __analysis_assume(ioQueueConfig.EvtIoStop == 0);
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed %!STATUS!\n", status);
+ goto Error;
+ }
+
+ //
+ // We will create a separate sequential queue and configure it
+ // to receive read requests. We also need to register a EvtIoStop
+ // handler so that we can acknowledge requests that are pending
+ // at the target driver.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);
+
+ ioQueueConfig.EvtIoRead = OsrFxEvtIoRead;
+ ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;
+
+ status = WdfIoQueueCreate(
+ device,
+ &ioQueueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &queue // queue handle
+ );
+
+ if (!NT_SUCCESS (status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed 0x%x\n", status);
+ goto Error;
+ }
+
+ status = WdfDeviceConfigureRequestDispatching(
+ device,
+ queue,
+ WdfRequestTypeRead);
+
+ if(!NT_SUCCESS (status)){
+ assert(NT_SUCCESS(status));
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
+ goto Error;
+ }
+
+
+ //
+ // We will create another sequential queue and configure it
+ // to receive write requests.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);
+
+ ioQueueConfig.EvtIoWrite = OsrFxEvtIoWrite;
+ ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;
+
+ status = WdfIoQueueCreate(
+ device,
+ &ioQueueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &queue // queue handle
+ );
+
+ if (!NT_SUCCESS (status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed 0x%x\n", status);
+ goto Error;
+ }
+
+ status = WdfDeviceConfigureRequestDispatching(
+ device,
+ queue,
+ WdfRequestTypeWrite);
+
+ if(!NT_SUCCESS (status)){
+ assert(NT_SUCCESS(status));
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceConfigureRequestDispatching failed 0x%x\n", status);
+ goto Error;
+ }
+
+ //
+ // Register a manual I/O queue for handling Interrupt Message Read Requests.
+ // This queue will be used for storing Requests that need to wait for an
+ // interrupt to occur before they can be completed.
+ //
+ WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual);
+
+ //
+ // This queue is used for requests that dont directly access the device. The
+ // requests in this queue are serviced only when the device is in a fully
+ // powered state and sends an interrupt. So we can use a non-power managed
+ // queue to park the requests since we dont care whether the device is idle
+ // or fully powered up.
+ //
+ ioQueueConfig.PowerManaged = WdfFalse;
+
+ status = WdfIoQueueCreate(device,
+ &ioQueueConfig,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &pDevContext->InterruptMsgQueue
+ );
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfIoQueueCreate failed 0x%x\n", status);
+ goto Error;
+ }
+
+ //
+ // Register a device interface so that app can find our device and talk to it.
+ //
+ status = WdfDeviceCreateDeviceInterface(device,
+ (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
+ NULL); // Reference String
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceCreateDeviceInterface failed %!STATUS!\n", status);
+ goto Error;
+ }
+
+ //
+ // Create the lock that we use to serialize calls to ResetDevice(). As an
+ // alternative to using a WDFWAITLOCK to serialize the calls, a sequential
+ // WDFQUEUE can be created and reset IOCTLs would be forwarded to it.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = device;
+
+ status = WdfWaitLockCreate(&attributes, &pDevContext->ResetDeviceWaitLock);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfWaitLockCreate failed %!STATUS!\n", status);
+ goto Error;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- OsrFxEvtDeviceAdd\n");
+
+ return status;
+
+Error:
+
+ //
+ // Log fail to add device to the event log
+ //
+ EventWriteFailAddDevice(pDevContext->DeviceName,
+ pDevContext->Location,
+ status);
+
+ return status;
+}
+
+NTSTATUS
+OsrFxEvtDevicePrepareHardware(
+ WDFDEVICE Device,
+ WDFCMRESLIST ResourceList,
+ 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 and selecting descriptors.
+
+Arguments:
+
+ Device - handle to a device
+
+ ResourceList - handle to a resource-list object that identifies the
+ raw hardware resources that the PnP manager assigned
+ to the device
+
+ ResourceListTranslated - handle to a resource-list object that
+ identifies the translated hardware resources
+ that the PnP manager assigned to the device
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ PDEVICE_CONTEXT pDeviceContext;
+ WDF_USB_DEVICE_INFORMATION deviceInfo;
+ ULONG waitWakeEnable;
+
+ UNREFERENCED_PARAMETER(ResourceList);
+ UNREFERENCED_PARAMETER(ResourceListTranslated);
+ waitWakeEnable = FALSE;
+ 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) {
+ status = WdfUsbTargetDeviceCreate(Device,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &pDeviceContext->UsbDevice);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfUsbTargetDeviceCreate failed with Status code %!STATUS!\n", status);
+ return status;
+ }
+ }
+
+ //
+ // Retrieve USBD version information, port driver capabilites and device
+ // capabilites such as speed, power, etc.
+ //
+ WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);
+
+ status = WdfUsbTargetDeviceRetrieveInformation(
+ pDeviceContext->UsbDevice,
+ &deviceInfo);
+ if (NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceHighSpeed: %s\n",
+ (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE");
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "IsDeviceSelfPowered: %s\n",
+ (deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE");
+
+ waitWakeEnable = deviceInfo.Traits &
+ WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
+ "IsDeviceRemoteWakeable: %s\n",
+ waitWakeEnable ? "TRUE" : "FALSE");
+ //
+ // Save these for use later.
+ //
+ pDeviceContext->UsbDeviceTraits = deviceInfo.Traits;
+ }
+ else {
+ pDeviceContext->UsbDeviceTraits = 0;
+ }
+
+ status = SelectInterfaces(Device);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "SelectInterfaces failed 0x%x\n", status);
+ return status;
+ }
+
+ //
+ // Enable wait-wake and idle timeout if the device supports it
+ //
+ if (waitWakeEnable) {
+ status = OsrFxSetPowerPolicy(Device);
+ if (!NT_SUCCESS (status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "OsrFxSetPowerPolicy failed %!STATUS!\n", status);
+ return status;
+ }
+ }
+
+ status = OsrFxConfigContReaderForInterruptEndPoint(pDeviceContext);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- EvtDevicePrepareHardware\n");
+
+ return status;
+}
+
+
+NTSTATUS
+OsrFxEvtDeviceD0Entry(
+ WDFDEVICE Device,
+ 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;
+ BOOLEAN isTargetStarted;
+
+ pDeviceContext = GetDeviceContext(Device);
+ isTargetStarted = FALSE;
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER,
+ "-->OsrFxEvtEvtDeviceD0Entry - coming from %s\n",
+ DbgDevicePowerString(PreviousState));
+
+ //
+ // Since continuous reader is configured for this interrupt-pipe, we must explicitly start
+ // the I/O target to get the framework to post read requests.
+ //
+ status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe));
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_POWER, "Failed to start interrupt pipe %!STATUS!\n", status);
+ goto End;
+ }
+
+ isTargetStarted = TRUE;
+
+End:
+
+ if (!NT_SUCCESS(status)) {
+ //
+ // Failure in D0Entry will lead to device being removed. So let us stop the continuous
+ // reader in preparation for the ensuing remove.
+ //
+ if (isTargetStarted) {
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe), WdfIoTargetCancelSentIo);
+ }
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--OsrFxEvtEvtDeviceD0Entry\n");
+
+ return status;
+}
+
+
+NTSTATUS
+OsrFxEvtDeviceD0Exit(
+ WDFDEVICE Device,
+ 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(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe), WdfIoTargetCancelSentIo);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--OsrFxEvtDeviceD0Exit\n");
+
+ return STATUS_SUCCESS;
+}
+
+VOID
+OsrFxEvtDeviceSelfManagedIoFlush(
+ _In_ WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ This routine handles flush activity for the device's
+ self-managed I/O operations.
+
+Arguments:
+
+ Device - Handle to a framework device object.
+
+Return Value:
+
+ None
+
+--*/
+{
+ // Service the interrupt message queue to drain any outstanding
+ // requests
+ OsrUsbIoctlGetInterruptMessage(Device, STATUS_DEVICE_REMOVED);
+}
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+OsrFxSetPowerPolicy(
+ _In_ WDFDEVICE Device
+ )
+{
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
+ WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ //
+ // Init the idle policy structure.
+ //
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
+ idleSettings.IdleTimeout = 10000; // 10-sec
+
+ status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
+ if ( !NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n", status);
+ return status;
+ }
+
+ //
+ // Init wait-wake policy structure.
+ //
+ WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
+
+ status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfDeviceAssignSxWakeSettings failed %x\n", status);
+ return status;
+ }
+
+ return status;
+}
+
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+SelectInterfaces(
+ _In_ WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ This helper routine selects the configuration, interface and
+ creates a context for every pipe (end point) in that interface.
+
+Arguments:
+
+ Device - Handle to a framework device
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
+ NTSTATUS status = STATUS_SUCCESS;
+ PDEVICE_CONTEXT pDeviceContext;
+ WDFUSBPIPE pipe;
+ WDF_USB_PIPE_INFORMATION pipeInfo;
+ UCHAR index;
+ UCHAR numberConfiguredPipes;
+ WDFUSBINTERFACE usbInterface;
+
+ PAGED_CODE();
+
+ pDeviceContext = GetDeviceContext(Device);
+
+ WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams);
+
+ usbInterface =
+ WdfUsbTargetDeviceGetInterface(pDeviceContext->UsbDevice, 0);
+
+ if (NULL == usbInterface) {
+ status = STATUS_UNSUCCESSFUL;
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "WdfUsbTargetDeviceGetInterface 0 failed %!STATUS! \n",
+ status);
+ return status;
+ }
+
+ configParams.Types.SingleInterface.ConfiguredUsbInterface =
+ usbInterface;
+
+ configParams.Types.SingleInterface.NumberConfiguredPipes =
+ WdfUsbInterfaceGetNumConfiguredPipes(usbInterface);
+
+ pDeviceContext->UsbInterface =
+ configParams.Types.SingleInterface.ConfiguredUsbInterface;
+
+ numberConfiguredPipes = configParams.Types.SingleInterface.NumberConfiguredPipes;
+
+ //
+ // Get pipe handles
+ //
+ for(index=0; index < numberConfiguredPipes; index++) {
+
+ WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
+
+ pipe = WdfUsbInterfaceGetConfiguredPipe(
+ pDeviceContext->UsbInterface,
+ index, //PipeIndex,
+ &pipeInfo
+ );
+ //
+ // Tell the framework that it's okay to read less than
+ // MaximumPacketSize
+ //
+ WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pipe);
+
+ if(WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) {
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
+ "Interrupt Pipe is 0x%p\n", pipe);
+ pDeviceContext->InterruptPipe = pipe;
+ }
+
+ if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
+ WdfUsbTargetPipeIsInEndpoint(pipe)) {
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
+ "BulkInput Pipe is 0x%p\n", pipe);
+ pDeviceContext->BulkReadPipe = pipe;
+ }
+
+ if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
+ WdfUsbTargetPipeIsOutEndpoint(pipe)) {
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL,
+ "BulkOutput Pipe is 0x%p\n", pipe);
+ pDeviceContext->BulkWritePipe = pipe;
+ }
+
+ }
+
+ //
+ // If we didn't find all the 3 pipes, fail the start.
+ //
+ if(!(pDeviceContext->BulkWritePipe
+ && pDeviceContext->BulkReadPipe && pDeviceContext->InterruptPipe)) {
+ status = STATUS_INVALID_DEVICE_STATE;
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
+ "Device is not configured properly %!STATUS!\n",
+ status);
+
+ return status;
+ }
+
+ return status;
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+VOID
+GetDeviceEventLoggingNames(
+ _In_ WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ Retrieve the friendly name and the location string into WDFMEMORY objects
+ and store them in the device context.
+
+Arguments:
+
+Return Value:
+
+ None
+
+--*/
+{
+ PDEVICE_CONTEXT pDevContext = GetDeviceContext(Device);
+
+ WDF_OBJECT_ATTRIBUTES objectAttributes;
+
+ WDFMEMORY deviceNameMemory = NULL;
+ WDFMEMORY locationMemory = NULL;
+
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // We want both memory objects to be children of the device so they will
+ // be deleted automatically when the device is removed.
+ //
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes);
+ objectAttributes.ParentObject = Device;
+
+ //
+ // First get the length of the string. If the FriendlyName
+ // is not there then get the lenght of device description.
+ //
+
+ status = WdfDeviceAllocAndQueryProperty(Device,
+ DevicePropertyFriendlyName,
+ NonPagedPoolNx,
+ &objectAttributes,
+ &deviceNameMemory);
+
+ if (!NT_SUCCESS(status))
+ {
+ status = WdfDeviceAllocAndQueryProperty(Device,
+ DevicePropertyDeviceDescription,
+ NonPagedPoolNx,
+ &objectAttributes,
+ &deviceNameMemory);
+ }
+
+ if (NT_SUCCESS(status))
+ {
+ pDevContext->DeviceNameMemory = deviceNameMemory;
+ pDevContext->DeviceName = WdfMemoryGetBuffer(deviceNameMemory, NULL);
+ }
+ else
+ {
+ pDevContext->DeviceNameMemory = NULL;
+ pDevContext->DeviceName = L"(error retrieving name)";
+ }
+
+ //
+ // Retrieve the device location string.
+ //
+
+ status = WdfDeviceAllocAndQueryProperty(Device,
+ DevicePropertyLocationInformation,
+ NonPagedPoolNx,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ &locationMemory);
+
+ if (NT_SUCCESS(status))
+ {
+ pDevContext->LocationMemory = locationMemory;
+ pDevContext->Location = WdfMemoryGetBuffer(locationMemory, NULL);
+ }
+ else
+ {
+ pDevContext->LocationMemory = NULL;
+ pDevContext->Location = L"(error retrieving location)";
+ }
+
+ return;
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+PCHAR
+DbgDevicePowerString(
+ _In_ WDF_POWER_DEVICE_STATE Type
+ )
+{
+ 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/umdf2_fx2/driver/bulkrwr.c b/usb/umdf2_fx2/driver/bulkrwr.c
new file mode 100644
index 00000000..83085da4
--- /dev/null
+++ b/usb/umdf2_fx2/driver/bulkrwr.c
@@ -0,0 +1,430 @@
+/*++
+
+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:
+
+ bulkrwr.c
+
+Abstract:
+
+ This file has routines to perform reads and writes.
+ The read and writes are targeted bulk to endpoints.
+
+Environment:
+
+ User mode
+
+--*/
+
+#include <osrusbfx2.h>
+
+
+#if defined(EVENT_TRACING)
+#include "bulkrwr.tmh"
+#endif
+
+#pragma warning(disable:4267)
+
+VOID
+OsrFxEvtIoRead(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t Length
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework when it receives Read or Write requests.
+
+Arguments:
+
+ Queue - Default queue handle
+ Request - Handle to the read/write request
+ Lenght - Length of the data buffer associated with the request.
+ The default property of the queue is to not dispatch
+ zero lenght read & write requests to the driver and
+ complete is with status success. So we will never get
+ a zero length request.
+
+Return Value:
+
+
+--*/
+{
+ WDFUSBPIPE pipe;
+ NTSTATUS status;
+ WDFMEMORY reqMemory;
+ PDEVICE_CONTEXT pDeviceContext;
+
+ UNREFERENCED_PARAMETER(Queue);
+
+ //
+ // Log read start event, using IRP activity ID if available or request
+ // handle otherwise.
+ //
+
+ EventWriteReadStart(WdfIoQueueGetDevice(Queue), (ULONG)Length);
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "-->OsrFxEvtIoRead\n");
+
+ //
+ // First validate input parameters.
+ //
+ if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Transfer exceeds %d\n",
+ TEST_BOARD_TRANSFER_BUFFER_SIZE);
+ status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
+
+ pipe = pDeviceContext->BulkReadPipe;
+
+ status = WdfRequestRetrieveOutputMemory(Request, &reqMemory);
+ if(!NT_SUCCESS(status)){
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
+ "WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status);
+ goto Exit;
+ }
+
+ //
+ // The format call validates to make sure that you are reading or
+ // writing to the right pipe type, sets the appropriate transfer flags,
+ // creates an URB and initializes the request.
+ //
+ status = WdfUsbTargetPipeFormatRequestForRead(pipe,
+ Request,
+ reqMemory,
+ NULL // Offsets
+ );
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
+ "WdfUsbTargetPipeFormatRequestForRead failed 0x%x\n", status);
+ goto Exit;
+ }
+
+ WdfRequestSetCompletionRoutine(
+ Request,
+ EvtRequestReadCompletionRoutine,
+ pipe);
+ //
+ // Send the request asynchronously.
+ //
+ if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
+ //
+ // Framework couldn't send the request for some reason.
+ //
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestSend failed\n");
+ status = WdfRequestGetStatus(Request);
+ goto Exit;
+ }
+
+
+Exit:
+ if (!NT_SUCCESS(status)) {
+ //
+ // log event read failed
+ //
+ EventWriteReadFail(WdfIoQueueGetDevice(Queue), status);
+ WdfRequestCompleteWithInformation(Request, status, 0);
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "<-- OsrFxEvtIoRead\n");
+
+ return;
+}
+
+VOID
+EvtRequestReadCompletionRoutine(
+ _In_ WDFREQUEST Request,
+ _In_ WDFIOTARGET Target,
+ _In_ PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
+ _In_ WDFCONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This is the completion routine for reads
+ If the irp completes with success, we check if we
+ need to recirculate this irp for another stage of
+ transfer.
+
+Arguments:
+
+ Context - Driver supplied context
+ Device - Device handle
+ Request - Request handle
+ Params - request completion params
+
+Return Value:
+ None
+
+--*/
+{
+ NTSTATUS status;
+ size_t bytesRead = 0;
+ PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;
+
+ UNREFERENCED_PARAMETER(Target);
+ UNREFERENCED_PARAMETER(Context);
+
+ status = CompletionParams->IoStatus.Status;
+
+ usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
+
+ bytesRead = usbCompletionParams->Parameters.PipeRead.Length;
+
+ if (NT_SUCCESS(status)){
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ,
+ "Number of bytes read: %I64d\n", (INT64)bytesRead);
+ } else {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
+ "Read failed - request status 0x%x UsbdStatus 0x%x\n",
+ status, usbCompletionParams->UsbdStatus);
+
+ }
+
+ //
+ // Log read stop event, using IRP activity ID if available or request
+ // handle otherwise.
+ //
+
+ EventWriteReadStop(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)),
+ bytesRead,
+ status,
+ usbCompletionParams->UsbdStatus);
+
+ WdfRequestCompleteWithInformation(Request, status, bytesRead);
+
+ return;
+}
+
+VOID
+OsrFxEvtIoWrite(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t Length
+ )
+/*++
+
+Routine Description:
+
+ Called by the framework when it receives Read or Write requests.
+
+Arguments:
+
+ Queue - Default queue handle
+ Request - Handle to the read/write request
+ Lenght - Length of the data buffer associated with the request.
+ The default property of the queue is to not dispatch
+ zero lenght read & write requests to the driver and
+ complete is with status success. So we will never get
+ a zero length request.
+
+Return Value:
+
+
+--*/
+{
+ NTSTATUS status;
+ WDFUSBPIPE pipe;
+ WDFMEMORY reqMemory;
+ PDEVICE_CONTEXT pDeviceContext;
+
+ UNREFERENCED_PARAMETER(Queue);
+
+
+ //
+ // Log write start event, using IRP activity ID if available or request
+ // handle otherwise.
+ //
+ EventWriteWriteStart(WdfIoQueueGetDevice(Queue), (ULONG)Length);
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "-->OsrFxEvtIoWrite\n");
+
+ //
+ // First validate input parameters.
+ //
+ if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Transfer exceeds %d\n",
+ TEST_BOARD_TRANSFER_BUFFER_SIZE);
+ status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
+
+ pipe = pDeviceContext->BulkWritePipe;
+
+ status = WdfRequestRetrieveInputMemory(Request, &reqMemory);
+ if(!NT_SUCCESS(status)){
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "WdfRequestRetrieveInputBuffer failed\n");
+ goto Exit;
+ }
+
+ status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
+ Request,
+ reqMemory,
+ NULL); // Offset
+
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "WdfUsbTargetPipeFormatRequestForWrite failed 0x%x\n", status);
+ goto Exit;
+ }
+
+ WdfRequestSetCompletionRoutine(
+ Request,
+ EvtRequestWriteCompletionRoutine,
+ pipe);
+
+ //
+ // Send the request asynchronously.
+ //
+ if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
+ //
+ // Framework couldn't send the request for some reason.
+ //
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "WdfRequestSend failed\n");
+ status = WdfRequestGetStatus(Request);
+ goto Exit;
+ }
+
+Exit:
+
+ if (!NT_SUCCESS(status)) {
+ //
+ // log event write failed
+ //
+ EventWriteWriteFail(WdfIoQueueGetDevice(Queue), status);
+
+ WdfRequestCompleteWithInformation(Request, status, 0);
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- OsrFxEvtIoWrite\n");
+
+ return;
+}
+
+VOID
+EvtRequestWriteCompletionRoutine(
+ _In_ WDFREQUEST Request,
+ _In_ WDFIOTARGET Target,
+ _In_ PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
+ _In_ WDFCONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This is the completion routine for writes
+ If the irp completes with success, we check if we
+ need to recirculate this irp for another stage of
+ transfer.
+
+Arguments:
+
+ Context - Driver supplied context
+ Device - Device handle
+ Request - Request handle
+ Params - request completion params
+
+Return Value:
+ None
+
+--*/
+{
+ NTSTATUS status;
+ size_t bytesWritten = 0;
+ PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;
+
+ UNREFERENCED_PARAMETER(Target);
+ UNREFERENCED_PARAMETER(Context);
+
+ status = CompletionParams->IoStatus.Status;
+
+ //
+ // For usb devices, we should look at the Usb.Completion param.
+ //
+ usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
+
+ bytesWritten = usbCompletionParams->Parameters.PipeWrite.Length;
+
+ if (NT_SUCCESS(status)){
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,
+ "Number of bytes written: %I64d\n", (INT64)bytesWritten);
+ } else {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
+ "Write failed: request Status 0x%x UsbdStatus 0x%x\n",
+ status, usbCompletionParams->UsbdStatus);
+ }
+
+ //
+ // Log write stop event, using IRP activtiy ID if available or request
+ // handle otherwise
+ //
+ EventWriteWriteStop(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)),
+ bytesWritten,
+ status,
+ usbCompletionParams->UsbdStatus);
+
+
+ WdfRequestCompleteWithInformation(Request, status, bytesWritten);
+
+ return;
+}
+
+
+VOID
+OsrFxEvtIoStop(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ ULONG ActionFlags
+ )
+/*++
+
+Routine Description:
+
+ This callback is invoked on every inflight request when the device
+ is suspended or removed. Since our inflight read and write requests
+ are actually pending in the target device, we will just acknowledge
+ its presence. Until we acknowledge, complete, or requeue the requests
+ framework will wait before allowing the device suspend or remove to
+ proceeed. When the underlying USB stack gets the request to suspend or
+ remove, it will fail all the pending requests.
+
+Arguments:
+
+ Queue - handle to queue object that is associated with the I/O request
+
+ Request - handle to a request object
+
+ ActionFlags - bitwise OR of one or more WDF_REQUEST_STOP_ACTION_FLAGS flags
+
+Return Value:
+ None
+
+--*/
+{
+ UNREFERENCED_PARAMETER(Queue);
+ UNREFERENCED_PARAMETER(ActionFlags);
+
+ if (ActionFlags & WdfRequestStopActionSuspend ) {
+ WdfRequestStopAcknowledge(Request, FALSE); // Don't requeue
+ } else if(ActionFlags & WdfRequestStopActionPurge) {
+ WdfRequestCancelSentRequest(Request);
+ }
+ return;
+}
+
+
diff --git a/usb/umdf2_fx2/driver/driver.c b/usb/umdf2_fx2/driver/driver.c
new file mode 100644
index 00000000..10bf3d39
--- /dev/null
+++ b/usb/umdf2_fx2/driver/driver.c
@@ -0,0 +1,277 @@
+/*++
+
+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 started,
+ (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:
+
+ User mode only
+
+--*/
+
+#include <osrusbfx2.h>
+
+#if defined(EVENT_TRACING)
+//
+// 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 trace.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"
+#else
+ULONG DebugLevel = TRACE_LEVEL_INFORMATION;
+ULONG DebugFlag = 0xff;
+#endif
+
+#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 or another NTSTATUS error code 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__);
+
+ //
+ // Register with ETW (unified tracing)
+ //
+ EventRegisterOSRUSBFX2();
+
+ //
+ // 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 Object 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);
+ EventUnregisterOSRUSBFX2();
+ }
+
+ return status;
+}
+
+VOID
+OsrFxEvtDriverContextCleanup(
+ WDFOBJECT Driver
+ )
+/*++
+Routine Description:
+
+ Free resources allocated in DriverEntry that are not automatically
+ cleaned up by the framework.
+
+Arguments:
+
+ Driver - handle to a WDF Driver object.
+
+Return Value:
+
+ VOID.
+
+--*/
+{
+ PAGED_CODE ();
+
+ UNREFERENCED_PARAMETER(Driver); // For the case when WPP is not being used.
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "--> OsrFxEvtDriverContextCleanup\n");
+
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER) Driver));
+
+ EventUnregisterOSRUSBFX2();
+}
+
+#if !defined(EVENT_TRACING)
+
+VOID
+TraceEvents (
+ _In_ ULONG DebugPrintLevel,
+ _In_ ULONG DebugPrintFlag,
+ _Printf_format_string_
+ _In_ PCSTR DebugMessage,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Debug print for the sample driver.
+
+Arguments:
+
+ DebugPrintLevel - print level between 0 and 3, with 3 the most verbose
+ DebugPrintFlag - message mask
+ DebugMessage - format string of the message to print
+ ... - values used by the format string
+
+Return Value:
+
+ None.
+
+ --*/
+ {
+#if DBG
+#define TEMP_BUFFER_SIZE 1024
+ va_list list;
+ CHAR debugMessageBuffer[TEMP_BUFFER_SIZE];
+ HRESULT hr;
+
+ va_start(list, DebugMessage);
+
+ if (DebugMessage) {
+
+ //
+ // Using new safe string functions instead of _vsnprintf.
+ // This function takes care of NULL terminating if the message
+ // is longer than the buffer.
+ //
+ hr = StringCchVPrintfA(debugMessageBuffer,
+ sizeof(debugMessageBuffer),
+ DebugMessage,
+ list);
+ if(FAILED(hr)) {
+ DbgPrint (_DRIVER_NAME_": StringCchVPrintfA failed with HRESULT 0x%x\n", hr);
+ return;
+ }
+ if (DebugPrintLevel <= TRACE_LEVEL_ERROR ||
+ (DebugPrintLevel <= DebugLevel &&
+ ((DebugPrintFlag & DebugFlag) == DebugPrintFlag))) {
+ DbgPrint("%s %s", _DRIVER_NAME_, debugMessageBuffer);
+ }
+ }
+ va_end(list);
+
+ return;
+#else
+ UNREFERENCED_PARAMETER(DebugPrintLevel);
+ UNREFERENCED_PARAMETER(DebugPrintFlag);
+ UNREFERENCED_PARAMETER(DebugMessage);
+#endif
+}
+
+#endif
+
+
+
+
diff --git a/usb/umdf2_fx2/driver/interrupt.c b/usb/umdf2_fx2/driver/interrupt.c
new file mode 100644
index 00000000..5983d936
--- /dev/null
+++ b/usb/umdf2_fx2/driver/interrupt.c
@@ -0,0 +1,184 @@
+/*++
+
+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:
+
+ User mode
+
+--*/
+
+#include <osrusbfx2.h>
+
+#if defined(EVENT_TRACING)
+#include "interrupt.tmh"
+#endif
+
+
+_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;
+
+ 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(DeviceContext->InterruptPipe,
+ &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;
+ }
+
+
+ assert(NumBytesTransferred == sizeof(UCHAR));
+
+ switchState = WdfMemoryGetBuffer(Buffer, NULL);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
+ "OsrFxEvtUsbInterruptPipeReadComplete SwitchState %x\n",
+ *switchState);
+
+ pDeviceContext->CurrentSwitchState = *switchState;
+
+ //
+ // Handle any pending Interrupt Message IOCTLs. Note that the OSR USB device
+ // will generate an interrupt message when the the device resumes from a low
+ // power state. So if the Interrupt Message IOCTL was sent after the device
+ // has gone to a low power state, the pending Interrupt Message IOCTL will
+ // get completed in the function call below, before the user twiddles the
+ // dip switches on the OSR USB device. If this is not the desired behavior
+ // for your driver, then you could handle this condition by maintaining a
+ // state variable on D0Entry to track interrupt messages caused by power up.
+ //
+ OsrUsbIoctlGetInterruptMessage(device, STATUS_SUCCESS);
+
+}
+
+BOOLEAN
+OsrFxEvtUsbInterruptReadersFailed(
+ _In_ WDFUSBPIPE Pipe,
+ _In_ NTSTATUS Status,
+ _In_ USBD_STATUS UsbdStatus
+ )
+{
+ WDFDEVICE device = WdfIoTargetGetDevice(WdfUsbTargetPipeGetIoTarget(Pipe));
+ PDEVICE_CONTEXT pDeviceContext = GetDeviceContext(device);
+
+ UNREFERENCED_PARAMETER(UsbdStatus);
+
+ //
+ // Clear the current switch state.
+ //
+ pDeviceContext->CurrentSwitchState = 0;
+
+ //
+ // Service the pending interrupt switch change request
+ //
+ OsrUsbIoctlGetInterruptMessage(device, Status);
+
+ return TRUE;
+}
+
diff --git a/usb/umdf2_fx2/driver/ioctl.c b/usb/umdf2_fx2/driver/ioctl.c
new file mode 100644
index 00000000..6312da35
--- /dev/null
+++ b/usb/umdf2_fx2/driver/ioctl.c
@@ -0,0 +1,1056 @@
+/*++
+
+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:
+
+ Ioctl.c
+
+Abstract:
+
+ USB device driver for OSR USB-FX2 Learning Kit
+
+Environment:
+
+ User mode only
+
+--*/
+
+#include <osrusbfx2.h>
+
+#if defined(EVENT_TRACING)
+#include "ioctl.tmh"
+#endif
+
+#pragma alloc_text(PAGE, OsrFxEvtIoDeviceControl)
+#pragma alloc_text(PAGE, ResetPipe)
+#pragma alloc_text(PAGE, ResetDevice)
+#pragma alloc_text(PAGE, ReenumerateDevice)
+#pragma alloc_text(PAGE, GetBarGraphState)
+#pragma alloc_text(PAGE, SetBarGraphState)
+#pragma alloc_text(PAGE, GetSevenSegmentState)
+#pragma alloc_text(PAGE, SetSevenSegmentState)
+#pragma alloc_text(PAGE, GetSwitchState)
+
+VOID
+OsrFxEvtIoDeviceControl(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode
+ )
+/*++
+
+Routine Description:
+
+ This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
+ requests from the system.
+
+Arguments:
+
+ Queue - Handle to the framework queue object that is associated
+ with the I/O request.
+ Request - Handle to a framework request object.
+
+ OutputBufferLength - length of the request's output buffer,
+ if an output buffer is available.
+ InputBufferLength - length of the request's input buffer,
+ if an input buffer is available.
+
+ IoControlCode - the driver-defined or system-defined I/O control code
+ (IOCTL) that is associated with the request.
+Return Value:
+
+ VOID
+
+--*/
+{
+ WDFDEVICE device;
+ PDEVICE_CONTEXT pDevContext;
+ size_t bytesReturned = 0;
+ PBAR_GRAPH_STATE barGraphState = NULL;
+ PSWITCH_STATE switchState = NULL;
+ PUCHAR sevenSegment = NULL;
+ BOOLEAN requestPending = FALSE;
+ NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
+
+ UNREFERENCED_PARAMETER(InputBufferLength);
+ UNREFERENCED_PARAMETER(OutputBufferLength);
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> OsrFxEvtIoDeviceControl\n");
+ //
+ // initialize variables
+ //
+ device = WdfIoQueueGetDevice(Queue);
+ pDevContext = GetDeviceContext(device);
+
+ switch(IoControlCode) {
+
+ case IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR: {
+
+ PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
+ USHORT requiredSize = 0;
+
+ //
+ // First get the size of the config descriptor
+ //
+ status = WdfUsbTargetDeviceRetrieveConfigDescriptor(
+ pDevContext->UsbDevice,
+ NULL,
+ &requiredSize);
+
+ if (status != STATUS_BUFFER_TOO_SMALL) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status);
+ break;
+ }
+
+ //
+ // Get the buffer - make sure the buffer is big enough
+ //
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ (size_t)requiredSize, // MinimumRequired
+ &configurationDescriptor,
+ NULL);
+ if(!NT_SUCCESS(status)){
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status);
+ break;
+ }
+
+ status = WdfUsbTargetDeviceRetrieveConfigDescriptor(
+ pDevContext->UsbDevice,
+ configurationDescriptor,
+ &requiredSize);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "WdfUsbTargetDeviceRetrieveConfigDescriptor failed 0x%x\n", status);
+ break;
+ }
+
+ bytesReturned = requiredSize;
+
+ }
+ break;
+
+ case IOCTL_OSRUSBFX2_RESET_DEVICE:
+
+ status = ResetDevice(device);
+ break;
+
+ case IOCTL_OSRUSBFX2_REENUMERATE_DEVICE:
+
+ //
+ // Otherwise, call our function to reenumerate the
+ // device
+ //
+ status = ReenumerateDevice(pDevContext);
+
+ bytesReturned = 0;
+ break;
+
+ case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY:
+
+ //
+ // Make sure the caller's output buffer is large enough
+ // to hold the state of the bar graph
+ //
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ sizeof(BAR_GRAPH_STATE),
+ &barGraphState,
+ NULL);
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "User's output buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n");
+ break;
+ }
+ //
+ // Call our function to get the bar graph state
+ //
+ status = GetBarGraphState(pDevContext, barGraphState);
+
+ //
+ // If we succeeded return the user their data
+ //
+ if (NT_SUCCESS(status)) {
+
+ bytesReturned = sizeof(BAR_GRAPH_STATE);
+
+ } else {
+
+ bytesReturned = 0;
+
+ }
+ break;
+
+ case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:
+
+ status = WdfRequestRetrieveInputBuffer(Request,
+ sizeof(BAR_GRAPH_STATE),
+ &barGraphState,
+ NULL);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "User's input buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n");
+ break;
+ }
+
+ //
+ // Call our routine to set the bar graph state
+ //
+ status = SetBarGraphState(pDevContext, barGraphState);
+
+ //
+ // There's no data returned for this call
+ //
+ bytesReturned = 0;
+ break;
+
+ case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY:
+
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ sizeof(UCHAR),
+ &sevenSegment,
+ NULL);
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "User's output buffer is too small for this IOCTL, expecting an UCHAR\n");
+ break;
+ }
+
+ //
+ // Call our function to get the 7 segment state
+ //
+ status = GetSevenSegmentState(pDevContext, sevenSegment);
+
+ //
+ // If we succeeded return the user their data
+ //
+ if (NT_SUCCESS(status)) {
+
+ bytesReturned = sizeof(UCHAR);
+
+ } else {
+
+ bytesReturned = 0;
+
+ }
+ break;
+
+ case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY:
+
+ status = WdfRequestRetrieveInputBuffer(Request,
+ sizeof(UCHAR),
+ &sevenSegment,
+ NULL);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "User's input buffer is too small for this IOCTL, expecting an UCHAR\n");
+ bytesReturned = sizeof(UCHAR);
+ break;
+ }
+
+ //
+ // Call our routine to set the 7 segment state
+ //
+ status = SetSevenSegmentState(pDevContext, sevenSegment);
+
+ //
+ // There's no data returned for this call
+ //
+ bytesReturned = 0;
+ break;
+
+ case IOCTL_OSRUSBFX2_READ_SWITCHES:
+
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ sizeof(SWITCH_STATE),
+ &switchState,
+ NULL);// BufferLength
+
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n");
+ bytesReturned = sizeof(SWITCH_STATE);
+ break;
+
+ }
+
+ //
+ // Call our routine to get the state of the switches
+ //
+ status = GetSwitchState(pDevContext, switchState);
+
+ //
+ // If successful, return the user their data
+ //
+ if (NT_SUCCESS(status)) {
+
+ bytesReturned = sizeof(SWITCH_STATE);
+
+ } else {
+ //
+ // Don't return any data
+ //
+ bytesReturned = 0;
+ }
+ break;
+
+ case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE:
+
+ //
+ // Forward the request to an interrupt message queue and dont complete
+ // the request until an interrupt from the USB device occurs.
+ //
+ status = WdfRequestForwardToIoQueue(Request, pDevContext->InterruptMsgQueue);
+ if (NT_SUCCESS(status)) {
+ requestPending = TRUE;
+ }
+
+ break;
+
+ default :
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ if (requestPending == FALSE) {
+ WdfRequestCompleteWithInformation(Request, status, bytesReturned);
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- OsrFxEvtIoDeviceControl\n");
+
+ return;
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+ResetPipe(
+ _In_ WDFUSBPIPE Pipe
+ )
+/*++
+
+Routine Description:
+
+ This routine resets the pipe.
+
+Arguments:
+
+ Pipe - framework pipe handle
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ //
+ // This routine synchronously submits a URB_FUNCTION_RESET_PIPE
+ // request down the stack.
+ //
+ status = WdfUsbTargetPipeResetSynchronously(Pipe,
+ WDF_NO_HANDLE, // WDFREQUEST
+ NULL // PWDF_REQUEST_SEND_OPTIONS
+ );
+
+ if (NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "ResetPipe - success\n");
+ status = STATUS_SUCCESS;
+ }
+ else {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetPipe - failed\n");
+ }
+
+ return status;
+}
+
+VOID
+StopAllPipes(
+ IN PDEVICE_CONTEXT DeviceContext
+ )
+{
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(DeviceContext->InterruptPipe),
+ WdfIoTargetCancelSentIo);
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkReadPipe),
+ WdfIoTargetCancelSentIo);
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkWritePipe),
+ WdfIoTargetCancelSentIo);
+}
+
+NTSTATUS
+StartAllPipes(
+ IN PDEVICE_CONTEXT DeviceContext
+ )
+{
+ NTSTATUS status;
+
+ status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(DeviceContext->InterruptPipe));
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkReadPipe));
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(DeviceContext->BulkWritePipe));
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ return status;
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+ResetDevice(
+ _In_ WDFDEVICE Device
+ )
+/*++
+
+Routine Description:
+
+ This routine calls WdfUsbTargetDeviceResetPortSynchronously to reset the device if it's still
+ connected.
+
+Arguments:
+
+ Device - Handle to a framework device
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ PDEVICE_CONTEXT pDeviceContext;
+ NTSTATUS status;
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> ResetDevice\n");
+
+ pDeviceContext = GetDeviceContext(Device);
+
+ //
+ // A NULL timeout indicates an infinite wake
+ //
+ status = WdfWaitLockAcquire(pDeviceContext->ResetDeviceWaitLock, NULL);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetDevice - could not acquire lock\n");
+ return status;
+ }
+
+ StopAllPipes(pDeviceContext);
+
+ status = WdfUsbTargetDeviceResetPortSynchronously(pDeviceContext->UsbDevice);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetDevice failed - 0x%x\n", status);
+ }
+
+ status = StartAllPipes(pDeviceContext);
+ if (!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Failed to start all pipes - 0x%x\n", status);
+ }
+
+ WdfWaitLockRelease(pDeviceContext->ResetDeviceWaitLock);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- ResetDevice\n");
+ return status;
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+ReenumerateDevice(
+ _In_ PDEVICE_CONTEXT DevContext
+ )
+/*++
+
+Routine Description
+
+ This routine re-enumerates the USB device.
+
+Arguments:
+
+ pDevContext - One of our device extensions
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_REQUEST_SEND_OPTIONS sendOptions;
+ GUID activity;
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,"--> ReenumerateDevice\n");
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(
+ &sendOptions,
+ WDF_REQUEST_SEND_OPTION_TIMEOUT
+ );
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
+ &sendOptions,
+ DEFAULT_CONTROL_TRANSFER_TIMEOUT
+ );
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_REENUMERATE, // Request
+ 0, // Value
+ 0); // Index
+
+
+ status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ DevContext->UsbDevice,
+ WDF_NO_HANDLE, // Optional WDFREQUEST
+ &sendOptions,
+ &controlSetupPacket,
+ NULL, // MemoryDescriptor
+ NULL); // BytesTransferred
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "ReenumerateDevice: Failed to Reenumerate - 0x%x \n", status);
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,"<-- ReenumerateDevice\n");
+
+ //
+ // Send event to eventlog
+ //
+
+ activity = DeviceToActivityId(WdfObjectContextGetObject(DevContext));
+ EventWriteDeviceReenumerated(DevContext->DeviceName,
+ DevContext->Location,
+ status);
+
+ return status;
+
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+GetBarGraphState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _Out_ PBAR_GRAPH_STATE BarGraphState
+ )
+/*++
+
+Routine Description
+
+ This routine gets the state of the bar graph on the board
+
+Arguments:
+
+ DevContext - One of our device extensions
+
+ BarGraphState - Struct that receives the bar graph's state
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_REQUEST_SEND_OPTIONS sendOptions;
+ WDF_MEMORY_DESCRIPTOR memDesc;
+ ULONG bytesTransferred;
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> GetBarGraphState\n");
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(
+ &sendOptions,
+ WDF_REQUEST_SEND_OPTION_TIMEOUT
+ );
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
+ &sendOptions,
+ DEFAULT_CONTROL_TRANSFER_TIMEOUT
+ );
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_BARGRAPH_DISPLAY, // Request
+ 0, // Value
+ 0); // Index
+
+ //
+ // Set the buffer to 0, the board will OR in everything that is set
+ //
+ BarGraphState->BarsAsUChar = 0;
+
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
+ BarGraphState,
+ sizeof(BAR_GRAPH_STATE));
+
+ status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ DevContext->UsbDevice,
+ WDF_NO_HANDLE, // Optional WDFREQUEST
+ &sendOptions,
+ &controlSetupPacket,
+ &memDesc,
+ &bytesTransferred);
+
+ if(!NT_SUCCESS(status)) {
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "GetBarGraphState: Failed to GetBarGraphState - 0x%x \n", status);
+
+ } else {
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,
+ "GetBarGraphState: LED mask is 0x%x\n", BarGraphState->BarsAsUChar);
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- GetBarGraphState\n");
+
+ return status;
+
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+SetBarGraphState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _In_ PBAR_GRAPH_STATE BarGraphState
+ )
+/*++
+
+Routine Description
+
+ This routine sets the state of the bar graph on the board
+
+Arguments:
+
+ DevContext - One of our device extensions
+
+ BarGraphState - Struct that describes the bar graph's desired state
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_REQUEST_SEND_OPTIONS sendOptions;
+ WDF_MEMORY_DESCRIPTOR memDesc;
+ ULONG bytesTransferred;
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> SetBarGraphState\n");
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(
+ &sendOptions,
+ WDF_REQUEST_SEND_OPTION_TIMEOUT
+ );
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
+ &sendOptions,
+ DEFAULT_CONTROL_TRANSFER_TIMEOUT
+ );
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_SET_BARGRAPH_DISPLAY, // Request
+ 0, // Value
+ 0); // Index
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
+ BarGraphState,
+ sizeof(BAR_GRAPH_STATE));
+
+ status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ DevContext->UsbDevice,
+ NULL, // Optional WDFREQUEST
+ &sendOptions,
+ &controlSetupPacket,
+ &memDesc,
+ &bytesTransferred);
+
+ if(!NT_SUCCESS(status)) {
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "SetBarGraphState: Failed - 0x%x \n", status);
+
+ } else {
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,
+ "SetBarGraphState: LED mask is 0x%x\n", BarGraphState->BarsAsUChar);
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- SetBarGraphState\n");
+
+ return status;
+
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+GetSevenSegmentState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _Out_ PUCHAR SevenSegment
+ )
+/*++
+
+Routine Description
+
+ This routine gets the state of the 7 segment display on the board
+ by sending a synchronous control command.
+
+ NOTE: It's not a good practice to send a synchronous request in the
+ context of the user thread because if the transfer takes long
+ time to complete, you end up holding the user thread.
+
+ I'm choosing to do synchronous transfer because a) I know this one
+ completes immediately b) and for demonstration.
+
+Arguments:
+
+ DevContext - One of our device extensions
+
+ SevenSegment - receives the state of the 7 segment display
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_REQUEST_SEND_OPTIONS sendOptions;
+
+ WDF_MEMORY_DESCRIPTOR memDesc;
+ ULONG bytesTransferred;
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSetSevenSegmentState: Enter\n");
+
+ PAGED_CODE();
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(
+ &sendOptions,
+ WDF_REQUEST_SEND_OPTION_TIMEOUT
+ );
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
+ &sendOptions,
+ DEFAULT_CONTROL_TRANSFER_TIMEOUT
+ );
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_7SEGMENT_DISPLAY, // Request
+ 0, // Value
+ 0); // Index
+
+ //
+ // Set the buffer to 0, the board will OR in everything that is set
+ //
+ *SevenSegment = 0;
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
+ SevenSegment,
+ sizeof(UCHAR));
+
+ status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ DevContext->UsbDevice,
+ NULL, // Optional WDFREQUEST
+ &sendOptions,
+ &controlSetupPacket,
+ &memDesc,
+ &bytesTransferred);
+
+ if(!NT_SUCCESS(status)) {
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "GetSevenSegmentState: Failed to get 7 Segment state - 0x%x \n", status);
+ } else {
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,
+ "GetSevenSegmentState: 7 Segment mask is 0x%x\n", *SevenSegment);
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "GetSetSevenSegmentState: Exit\n");
+
+ return status;
+
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+SetSevenSegmentState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _In_ PUCHAR SevenSegment
+ )
+/*++
+
+Routine Description
+
+ This routine sets the state of the 7 segment display on the board
+
+Arguments:
+
+ DevContext - One of our device extensions
+
+ SevenSegment - desired state of the 7 segment display
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_REQUEST_SEND_OPTIONS sendOptions;
+ WDF_MEMORY_DESCRIPTOR memDesc;
+ ULONG bytesTransferred;
+
+ PAGED_CODE();
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> SetSevenSegmentState\n");
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(
+ &sendOptions,
+ WDF_REQUEST_SEND_OPTION_TIMEOUT
+ );
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
+ &sendOptions,
+ DEFAULT_CONTROL_TRANSFER_TIMEOUT
+ );
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
+ BmRequestHostToDevice,
+ BmRequestToDevice,
+ USBFX2LK_SET_7SEGMENT_DISPLAY, // Request
+ 0, // Value
+ 0); // Index
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
+ SevenSegment,
+ sizeof(UCHAR));
+
+ status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ DevContext->UsbDevice,
+ NULL, // Optional WDFREQUEST
+ &sendOptions,
+ &controlSetupPacket,
+ &memDesc,
+ &bytesTransferred);
+
+ if(!NT_SUCCESS(status)) {
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "SetSevenSegmentState: Failed to set 7 Segment state - 0x%x \n", status);
+
+ } else {
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,
+ "SetSevenSegmentState: 7 Segment mask is 0x%x\n", *SevenSegment);
+
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- SetSevenSegmentState\n");
+
+ return status;
+
+}
+
+_IRQL_requires_(PASSIVE_LEVEL)
+NTSTATUS
+GetSwitchState(
+ _In_ PDEVICE_CONTEXT DevContext,
+ _In_ PSWITCH_STATE SwitchState
+ )
+/*++
+
+Routine Description
+
+ This routine gets the state of the switches on the board
+
+Arguments:
+
+ DevContext - One of our device extensions
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_REQUEST_SEND_OPTIONS sendOptions;
+ WDF_MEMORY_DESCRIPTOR memDesc;
+ ULONG bytesTransferred;
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "--> GetSwitchState\n");
+
+ PAGED_CODE();
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(
+ &sendOptions,
+ WDF_REQUEST_SEND_OPTION_TIMEOUT
+ );
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
+ &sendOptions,
+ DEFAULT_CONTROL_TRANSFER_TIMEOUT
+ );
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
+ BmRequestDeviceToHost,
+ BmRequestToDevice,
+ USBFX2LK_READ_SWITCHES, // Request
+ 0, // Value
+ 0); // Index
+
+ SwitchState->SwitchesAsUChar = 0;
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc,
+ SwitchState,
+ sizeof(SWITCH_STATE));
+
+ status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ DevContext->UsbDevice,
+ NULL, // Optional WDFREQUEST
+ &sendOptions,
+ &controlSetupPacket,
+ &memDesc,
+ &bytesTransferred);
+
+ if(!NT_SUCCESS(status)) {
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "GetSwitchState: Failed to Get switches - 0x%x \n", status);
+
+ } else {
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,
+ "GetSwitchState: Switch mask is 0x%x\n", SwitchState->SwitchesAsUChar);
+ }
+
+ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "<-- GetSwitchState\n");
+
+ return status;
+
+}
+
+
+VOID
+OsrUsbIoctlGetInterruptMessage(
+ _In_ WDFDEVICE Device,
+ _In_ NTSTATUS ReaderStatus
+ )
+/*++
+
+Routine Description
+
+ This method handles the completion of the pended request for the IOCTL
+ IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE.
+
+Arguments:
+
+ Device - Handle to a framework device.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS status;
+ WDFREQUEST request;
+ PDEVICE_CONTEXT pDevContext;
+ size_t bytesReturned = 0;
+ PSWITCH_STATE switchState = NULL;
+
+ pDevContext = GetDeviceContext(Device);
+
+ do {
+
+ //
+ // Check if there are any pending requests in the Interrupt Message Queue.
+ // If a request is found then complete the pending request.
+ //
+ status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request);
+
+ if (NT_SUCCESS(status)) {
+ status = WdfRequestRetrieveOutputBuffer(request,
+ sizeof(SWITCH_STATE),
+ &switchState,
+ NULL);// BufferLength
+
+ if (!NT_SUCCESS(status)) {
+
+ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL,
+ "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n");
+ bytesReturned = sizeof(SWITCH_STATE);
+
+ } else {
+
+ //
+ // Copy the state information saved by the continuous reader.
+ //
+ if (NT_SUCCESS(ReaderStatus)) {
+ switchState->SwitchesAsUChar = pDevContext->CurrentSwitchState;
+ bytesReturned = sizeof(SWITCH_STATE);
+ } else {
+ bytesReturned = 0;
+ }
+ }
+
+ //
+ // Complete the request. If we failed to get the output buffer then
+ // complete with that status. Otherwise complete with the status from the reader.
+ //
+ WdfRequestCompleteWithInformation(request,
+ NT_SUCCESS(status) ? ReaderStatus : status,
+ bytesReturned);
+ status = STATUS_SUCCESS;
+
+ } else if (status != STATUS_NO_MORE_ENTRIES) {
+ KdPrint(("WdfIoQueueRetrieveNextRequest status %08x\n", status));
+ }
+
+ request = NULL;
+
+ } while (status == STATUS_SUCCESS);
+
+ return;
+
+}
+
+
diff --git a/usb/umdf2_fx2/driver/osrusbfx2.h b/usb/umdf2_fx2/driver/osrusbfx2.h
new file mode 100644
index 00000000..d59837fc
--- /dev/null
+++ b/usb/umdf2_fx2/driver/osrusbfx2.h
@@ -0,0 +1,312 @@
+/*++
+
+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:
+
+ User mode
+
+--*/
+
+#include <windows.h>
+#include <winioctl.h>
+#pragma warning( disable: 4201 ) // nonstandard extension used : nameless struct/union
+#include <ntstatus.h>
+#include <assert.h>
+#include <strsafe.h>
+#include <devpropdef.h>
+#include <wudfwdm.h>
+typedef struct _IO_STACK_LOCATION *PIO_STACK_LOCATION;
+#include "usbdi.h"
+#include <wdf.h>
+#include <wdfusb.h>
+#include "prototypes.h"
+#include "initguid.h"
+#include "public.h"
+#include "driverspecs.h"
+
+#include "trace.h"
+
+//
+// Include auto-generated ETW event functions (created by MC.EXE from
+// osrusbfx2.man)
+//
+#include <evntprov.h>
+#include "fx2Events.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;
+
+ WDFUSBPIPE BulkReadPipe;
+
+ WDFUSBPIPE BulkWritePipe;
+
+ WDFUSBPIPE InterruptPipe;
+
+ WDFWAITLOCK ResetDeviceWaitLock;
+
+ UCHAR CurrentSwitchState;
+
+ WDFQUEUE InterruptMsgQueue;
+
+ ULONG UsbDeviceTraits;
+
+ //
+ // The following fields are used during event logging to
+ // report the events relative to this specific instance
+ // of the device.
+ //
+
+ WDFMEMORY DeviceNameMemory;
+ PCWSTR DeviceName;
+
+ WDFMEMORY LocationMemory;
+ PCWSTR Location;
+
+} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)
+
+extern ULONG DebugLevel;
+
+typedef
+NTSTATUS
+(*PFN_IO_GET_ACTIVITY_ID_IRP) (
+ _In_ PIRP Irp,
+ _Out_ LPGUID Guid
+ );
+
+typedef
+NTSTATUS
+(*PFN_IO_SET_DEVICE_INTERFACE_PROPERTY_DATA) (
+ _In_ PUNICODE_STRING SymbolicLinkName,
+ _In_ CONST DEVPROPKEY *PropertyKey,
+ _In_ LCID Lcid,
+ _In_ ULONG Flags,
+ _In_ DEVPROPTYPE Type,
+ _In_ ULONG Size,
+ _In_opt_ PVOID Data
+ );
+
+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
+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
+ );
+
+VOID
+OsrUsbIoctlGetInterruptMessage(
+ _In_ WDFDEVICE Device,
+ _In_ NTSTATUS ReaderStatus
+ );
+
+_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;
+
+EVT_WDF_DEVICE_SELF_MANAGED_IO_FLUSH OsrFxEvtDeviceSelfManagedIoFlush;
+
+_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)
+VOID
+GetDeviceEventLoggingNames(
+ _In_ WDFDEVICE Device
+ );
+
+_IRQL_requires_(PASSIVE_LEVEL)
+PCHAR
+DbgDevicePowerString(
+ _In_ WDF_POWER_DEVICE_STATE Type
+ );
+
+FORCEINLINE
+GUID
+RequestToActivityId(
+ _In_ WDFREQUEST Request
+ )
+{
+ GUID activity = {0};
+
+ //
+ // Use the WDFREQUEST handle as the activity ID
+ //
+ RtlCopyMemory(&activity, &Request, sizeof(WDFREQUEST));
+
+ return activity;
+}
+
+FORCEINLINE
+GUID
+DeviceToActivityId(
+ _In_ WDFDEVICE Device
+ )
+{
+ GUID activity = {0};
+ RtlCopyMemory(&activity, &Device, sizeof(WDFDEVICE));
+ return activity;
+}
+
+
+#endif
+
+
diff --git a/usb/umdf2_fx2/driver/osrusbfx2.man b/usb/umdf2_fx2/driver/osrusbfx2.man
new file mode 100644
index 00000000..19f363d5
--- /dev/null
+++ b/usb/umdf2_fx2/driver/osrusbfx2.man
@@ -0,0 +1,309 @@
+<?xml version='1.0' encoding='utf-8' standalone='yes'?>
+<instrumentationManifest
+ xmlns="http://schemas.microsoft.com/win/2004/08/events"
+ xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
+ >
+ <instrumentation>
+ <events>
+ <provider
+ guid="{69cd60e3-430f-4da4-b1b3-e3bdaf945875}"
+ messageFileName="%Systemroot%\System32\drivers\umdf\osrusbfx2um.dll"
+ name="OSRUSBFX2"
+ resourceFileName="%SystemRoot%\System32\drivers\umdf\osrusbfx2um.dll"
+ symbol="OSRUSBFX2_PROVIDER"
+ >
+ <channels>
+ <channel
+ chid="Analytic"
+ enabled="false"
+ name="OsrUsbfx2/Analytic"
+ symbol="OSRUSBFX2_ANALYTIC"
+ type="Analytic"
+ />
+ <channel
+ chid="operational"
+ enabled="true"
+ isolation="System"
+ message="$(string.OSRUSBFX2_OPERATIONAL.Name)"
+ name="OsrUsbFx2/Operational"
+ symbol="OSRUSBFX2_OPERATIONAL"
+ type="Operational"
+ />
+ </channels>
+ <keywords>
+ <keyword
+ mask="0x0000000000000010"
+ message="$(string.OSRUSBFX2_DEVICE_INFO_KEYWORD.message)"
+ name="deviceinfo"
+ symbol="OSRUSBFX2_DEVICE_INFO_KEYWORD"
+ />
+ <keyword
+ mask="0x0000000000000040"
+ message="$(string.OSRUSBFX2_READ_WRITE_KEYWORD.message)"
+ name="readwrite"
+ symbol="OSRUSBFX2_READ_WRITE_KEYWORD"
+ />
+ </keywords>
+ <opcodes>
+ <!-- Defining our own custom opcode instead of using standard opcodes defined by winmeta.xml -->
+ <opcode
+ name="add"
+ symbol="OSRUSBFX2_DEVICE_ADD"
+ value="10"
+ />
+ <opcode
+ name="fail"
+ symbol="OSRUSBFX2_FAIL"
+ value="11"
+ />
+ </opcodes>
+ <tasks>
+ <!-- Support for XP and W2K3 : MC.exe will create a MOF file -->
+ <!-- Requires an associated eventGUID attribute for each task that is defined -->
+ <!-- For the MOF file : -->
+ <!-- Semantically, the event GUID represents a set of logical events that are logged by the provider. -->
+ <task
+ eventGUID="{872c3c43-6899-4f1d-89b8-51a82f6db657}"
+ name="deviceInit"
+ symbol="OSRUSBFX2_DEVICE_INIT"
+ value="1"
+ />
+ <task
+ eventGUID="{872c3c45-6899-4f1d-89b8-51a82f6db657}"
+ name="read"
+ symbol="OSRUSBFX2_READ"
+ value="2"
+ />
+ <task
+ eventGUID="{872c3c46-6899-4f1d-89b8-51a82f6db657}"
+ name="write"
+ symbol="OSRUSBFX2_WRITE"
+ value="3"
+ />
+ </tasks>
+ <templates>
+ <template tid="tid_DeviceStatus">
+ <data
+ inType="win:UnicodeString"
+ name="FriendlyName"
+ outType="xs:string"
+ />
+ <data
+ inType="win:UnicodeString"
+ name="Location"
+ outType="xs:string"
+ />
+ <data
+ inType="win:UInt32"
+ name="NTStatus"
+ outType="xs:HexInt32"
+ />
+ </template>
+ <template tid="tid_ReadWrite">
+ <data
+ inType="win:Pointer"
+ name="Device"
+ outType="win:HexInt64"
+ />
+ <data
+ inType="win:UInt32"
+ name="Length"
+ outType="xs:unsignedInt"
+ />
+ </template>
+ <template tid="tid_ReadWriteFail">
+ <data
+ inType="win:Pointer"
+ name="Device"
+ outType="win:HexInt64"
+ />
+ <data
+ inType="win:UInt32"
+ name="NTStatus"
+ outType="xs:HexInt32"
+ />
+ </template>
+ <template tid="tid_ReadWriteCompletion">
+ <data
+ inType="win:Pointer"
+ name="Device"
+ outType="win:HexInt64"
+ />
+ <data
+ inType="win:UInt32"
+ name="Length"
+ outType="xs:unsignedInt"
+ />
+ <data
+ inType="win:UInt32"
+ name="NTStatus"
+ outType="xs:HexInt32"
+ />
+ <data
+ inType="win:UInt32"
+ name="UsbdStatus"
+ outType="xs:unsignedInt"
+ />
+ </template>
+ </templates>
+ <events>
+ <event
+ channel="Analytic"
+ keywords="readwrite"
+ message="$(string.ReadStart.EventMessage)"
+ level="win:Informational"
+ opcode="win:Start"
+ symbol="ReadStart"
+ task="read"
+ template="tid_ReadWrite"
+ value="1"
+ />
+ <event
+ channel="Analytic"
+ keywords="readwrite"
+ message="$(string.ReadStop.EventMessage)"
+ level="win:Informational"
+ opcode="win:Stop"
+ symbol="ReadStop"
+ task="read"
+ template="tid_ReadWriteCompletion"
+ value="2"
+ />
+ <event
+ channel="Analytic"
+ keywords="readwrite"
+ message="$(string.ReadFail.EventMessage)"
+ level="win:Error"
+ opcode="fail"
+ symbol="ReadFail"
+ task="read"
+ template="tid_ReadWriteFail"
+ value="3"
+ />
+ <event
+ channel="Analytic"
+ keywords="readwrite"
+ message="$(string.WriteStart.EventMessage)"
+ level="win:Informational"
+ opcode="win:Start"
+ symbol="WriteStart"
+ task="write"
+ template="tid_ReadWrite"
+ value="4"
+ />
+ <event
+ channel="Analytic"
+ keywords="readwrite"
+ message="$(string.WriteStop.EventMessage)"
+ level="win:Informational"
+ opcode="win:Stop"
+ symbol="WriteStop"
+ task="write"
+ template="tid_ReadWriteCompletion"
+ value="5"
+ />
+ <event
+ channel="Analytic"
+ keywords="readwrite"
+ message="$(string.WriteFail.EventMessage)"
+ level="win:Error"
+ opcode="fail"
+ symbol="WriteFail"
+ task="write"
+ template="tid_ReadWriteFail"
+ value="6"
+ />
+ <event
+ channel="operational"
+ keywords="deviceinfo"
+ level="win:Error"
+ message="$(string.DeviceFailAdd.EventMessage)"
+ opcode="add"
+ symbol="FailAddDevice"
+ task="deviceInit"
+ template="tid_DeviceStatus"
+ value="100"
+ />
+ <event
+ channel="operational"
+ keywords="deviceinfo"
+ message="$(string.DeviceReenumerated.EventMessage)"
+ opcode="win:Start"
+ symbol="DeviceReenumerated"
+ task="deviceInit"
+ template="tid_DeviceStatus"
+ value="101"
+ />
+ <event
+ channel="operational"
+ keywords="deviceinfo"
+ level="win:Error"
+ message="$(string.SelectConfigFailure.Message)"
+ opcode="fail"
+ symbol="SelectConfigFailure"
+ task="deviceInit"
+ template="tid_DeviceStatus"
+ value="102"
+ />
+ </events>
+ </provider>
+ </events>
+ </instrumentation>
+ <localization xmlns="http://schemas.microsoft.com/win/2004/08/events">
+ <resources culture="en-US">
+ <stringTable>
+ <string
+ id="OSRUSBFX2_DEVICE_INFO_KEYWORD.message"
+ value="Device events: fail to load, reenumerate"
+ />
+ <string
+ id="OSRUSBFX2_READ_WRITE_KEYWORD.message"
+ value="Read, Write events"
+ />
+ <string
+ id="OSRUSBFX2_OPERATIONAL.Name"
+ value="Operational channel eventlog"
+ />
+ <string
+ id="ReadStart.EventMessage"
+ value="Read. Device = %1, Length = %2"
+ />
+ <string
+ id="ReadStop.EventMessage"
+ value="Read complete. Device = %1, Length = %2, Status = %3, UsbStatus = %4"
+ />
+ <string
+ id="ReadFail.EventMessage"
+ value="Read error. Device = %1, Status = %2"
+ />
+ <string
+ id="WriteStart.EventMessage"
+ value="Write. Device = %1, Length = %2"
+ />
+ <string
+ id="WriteStop.EventMessage"
+ value="Write complete. Device = %1, Length = %2, Status = %3, UsbStatus = %4"
+ />
+ <string
+ id="WriteFail.EventMessage"
+ value="Write error. Device = %1, Status = %2"
+ />
+ <string
+ id="DeviceReenumerated.EventMessage"
+ value="Device %1 (location %2) was reenumerated"
+ />
+ <string
+ id="DeviceFailAdd.EventMessage"
+ value="Fail to add device %1 (location %2), status %3"
+ />
+ <string
+ id="SelectConfigFailure.Message"
+ value="This error occurs when an OSR USB Fx2 board is attached to a USB 1.1 port on a machine running Windows Vista. This error occurs because the OSR USB Fx2 board's Interrupt end-point descriptor does not conform to the USB specification. Windows Vista detects this and returns an error. You should plug the device into a USB 2.0 (or higher) port."
+ />
+ </stringTable>
+ </resources>
+ </localization>
+</instrumentationManifest>
diff --git a/usb/umdf2_fx2/driver/osrusbfx2.rc b/usb/umdf2_fx2/driver/osrusbfx2.rc
new file mode 100644
index 00000000..84f89a6c
--- /dev/null
+++ b/usb/umdf2_fx2/driver/osrusbfx2.rc
@@ -0,0 +1,13 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "WDF Sample Driver for OSR USB-FX2 Learning Kit"
+#define VER_INTERNALNAME_STR "osrusbfx2um.dll"
+#define VER_ORIGINALFILENAME_STR "osrusbfx2um.dll"
+
+#include "common.ver"
+
+#include "fx2Events.rc"
diff --git a/usb/umdf2_fx2/driver/osrusbfx2um.inx b/usb/umdf2_fx2/driver/osrusbfx2um.inx
new file mode 100644
index 00000000..bd01bb16
--- /dev/null
+++ b/usb/umdf2_fx2/driver/osrusbfx2um.inx
@@ -0,0 +1,103 @@
+;/*++
+;
+;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:
+;
+; OsrUsbFx2Um.INF
+;
+;Abstract:
+; Installation inf for OSR USB User-mode driver on FX2 Learning Kit
+;
+;--*/
+
+[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]
+osrusbfx2um.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]
+UmdfDispatcher=WinUsb
+UmdfService=WUDFOsrUsbFx2, WUDFOsrUsbFx2_Install
+UmdfServiceOrder=WUDFOsrUsbFx2
+
+[WUDFOsrUsbFx2_Install]
+UmdfLibraryVersion=$UMDFVERSION$
+ServiceBinary="%12%\UMDF\osrusbfx2um.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
+
+[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
+
+[DestinationDirs]
+UMDriverCopy=12,UMDF ; copy to driversMdf
+CoInstallers_CopyFiles=11
+
+[UMDriverCopy]
+osrusbfx2um.dll
+
+; =================== 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 2.0 Sample Driver for OSR USB Fx2 Learning Kit"
+WinUsb_SvcDesc="WinUSB Driver"
diff --git a/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj b/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj
new file mode 100644
index 00000000..44f6d46f
--- /dev/null
+++ b/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj
@@ -0,0 +1,216 @@
+<?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>{33535CCD-5A39-4FDC-9C3A-796896CE065B}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{0818D84E-7C44-4668-BCC4-CBE4610E615B}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</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>Universal</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>Universal</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>Universal</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="driver.c; device.c; ioctl.c; bulkrwr.c; Interrupt.c">
+ <WppEnabled>true</WppEnabled>
+ <WppDllMacro>true</WppDllMacro>
+ <WppTraceFunction>TraceEvents(LEVEL,FLAGS,MSG,...)</WppTraceFunction>
+ <WppGenerateUsingTemplateFile>{um-default.tpl}*.tmh</WppGenerateUsingTemplateFile>
+ <WppPreprocessorDefinitions>ENABLE_WPP_RECORDER=1;WPP_MACRO_USE_KM_VERSION_FOR_UM=1</WppPreprocessorDefinitions>
+ </ClCompile>
+ <Inf Include=".\osrusbfx2um.inx">
+ <Architecture>$(InfArch)</Architecture>
+ <SpecifyArchitecture>true</SpecifyArchitecture>
+ <CopyOutput>.\$(IntDir)\osrusbfx2um.inf</CopyOutput>
+ </Inf>
+ <MessageCompile Include="osrusbfx2.man">
+ <GenerateUserModeLoggingMacros>true</GenerateUserModeLoggingMacros>
+ <GenerateMofFile>true</GenerateMofFile>
+ <HeaderFilePath>.\$(IntDir)</HeaderFilePath>
+ <GeneratedHeaderPath>true</GeneratedHeaderPath>
+ <RCFilePath>.\$(IntDir)</RCFilePath>
+ <GeneratedRCAndMessagesPath>true</GeneratedRCAndMessagesPath>
+ <GeneratedFilesBaseName>fx2Events</GeneratedFilesBaseName>
+ <UseBaseNameOfInput>true</UseBaseNameOfInput>
+ </MessageCompile>
+ </ItemGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>osrusbfx2um</TargetName>
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>osrusbfx2um</TargetName>
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>osrusbfx2um</TargetName>
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>osrusbfx2um</TargetName>
+ <ALLOW_DATE_TIME>1</ALLOW_DATE_TIME>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);EVENT_TRACING;UNICODE;_UNICODE</PreprocessorDefinitions>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\mincore.lib;$(SDK_LIB_PATH)\WppRecorderUM.lib</AdditionalDependencies>
+ </Link>
+ </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/umdf2_fx2/driver/osrusbfx2um.vcxproj.Filters b/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj.Filters
new file mode 100644
index 00000000..e9fac5a4
--- /dev/null
+++ b/usb/umdf2_fx2/driver/osrusbfx2um.vcxproj.Filters
@@ -0,0 +1,51 @@
+<?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>{52B04D2F-A9FC-4C03-9A04-DF29F0A760BD}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{0A38487D-5A95-4D22-856A-29C215B94BA6}</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>{455882CC-7C61-4EF5-BA09-0B6A70C234A9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{FFADC7F2-84FB-45BC-BA65-1447A12B4727}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="bulkrwr.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <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="ioctl.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include=".\Debug\\osrusbfx2um.inf">
+ <Filter>Driver Files</Filter>
+ </FilesToPackage>
+ <Inf Include=".\osrusbfx2um.inx">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <MessageCompile Include="osrusbfx2.man">
+ <Filter>Resource Files</Filter>
+ </MessageCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf2_fx2/driver/trace.h b/usb/umdf2_fx2/driver/trace.h
new file mode 100644
index 00000000..5a72dcaf
--- /dev/null
+++ b/usb/umdf2_fx2/driver/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(RegistryPath)
+#define WPP_CLEANUP()
+
+#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
+
+
+
diff --git a/usb/umdf2_fx2/exe/dump.c b/usb/umdf2_fx2/exe/dump.c
new file mode 100644
index 00000000..69074bf1
--- /dev/null
+++ b/usb/umdf2_fx2/exe/dump.c
@@ -0,0 +1,444 @@
+/*++
+
+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:
+
+ DUMP.C
+
+Abstract:
+
+ Routines to dump the descriptors information in a human readable form.
+
+Environment:
+
+ user mode only
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "devioctl.h"
+
+#pragma warning(disable:4200) //
+#pragma warning(disable:4201) // nameless struct/union
+#pragma warning(disable:4214) // bit field types other than int
+
+#include <basetyps.h>
+#include "usbdi.h"
+#include "public.h"
+
+#pragma warning(default:4200)
+#pragma warning(default:4201)
+#pragma warning(default:4214)
+
+HANDLE
+OpenDevice(
+ _In_ BOOL Synchronous
+ );
+
+
+char*
+usbDescriptorTypeString(UCHAR bDescriptorType )
+/*++
+Routine Description:
+
+ Called to get ascii string of USB descriptor
+
+Arguments:
+
+ PUSB_ENDPOINT_DESCRIPTOR->bDescriptorType or
+ PUSB_DEVICE_DESCRIPTOR->bDescriptorType or
+ PUSB_INTERFACE_DESCRIPTOR->bDescriptorType or
+ PUSB_STRING_DESCRIPTOR->bDescriptorType or
+ PUSB_POWER_DESCRIPTOR->bDescriptorType or
+ PUSB_CONFIGURATION_DESCRIPTOR->bDescriptorType
+
+Return Value:
+
+ ptr to string
+
+--*/
+{
+
+ switch(bDescriptorType) {
+
+ case USB_DEVICE_DESCRIPTOR_TYPE:
+ return "USB_DEVICE_DESCRIPTOR_TYPE";
+
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+ return "USB_CONFIGURATION_DESCRIPTOR_TYPE";
+
+
+ case USB_STRING_DESCRIPTOR_TYPE:
+ return "USB_STRING_DESCRIPTOR_TYPE";
+
+
+ case USB_INTERFACE_DESCRIPTOR_TYPE:
+ return "USB_INTERFACE_DESCRIPTOR_TYPE";
+
+
+ case USB_ENDPOINT_DESCRIPTOR_TYPE:
+ return "USB_ENDPOINT_DESCRIPTOR_TYPE";
+
+
+#ifdef USB_POWER_DESCRIPTOR_TYPE // this is the older definintion which is actually obsolete
+ // workaround for temporary bug in 98ddk, older USB100.h file
+ case USB_POWER_DESCRIPTOR_TYPE:
+ return "USB_POWER_DESCRIPTOR_TYPE";
+#endif
+
+#ifdef USB_RESERVED_DESCRIPTOR_TYPE // this is the current version of USB100.h as in NT5DDK
+
+ case USB_RESERVED_DESCRIPTOR_TYPE:
+ return "USB_RESERVED_DESCRIPTOR_TYPE";
+
+ case USB_CONFIG_POWER_DESCRIPTOR_TYPE:
+ return "USB_CONFIG_POWER_DESCRIPTOR_TYPE";
+
+ case USB_INTERFACE_POWER_DESCRIPTOR_TYPE:
+ return "USB_INTERFACE_POWER_DESCRIPTOR_TYPE";
+#endif // for current nt5ddk version of USB100.h
+
+ default:
+ return "??? UNKNOWN!!";
+ }
+}
+
+
+char *
+usbEndPointTypeString(UCHAR bmAttributes)
+/*++
+Routine Description:
+
+ Called to get ascii string of endpt descriptor type
+
+Arguments:
+
+ PUSB_ENDPOINT_DESCRIPTOR->bmAttributes
+
+Return Value:
+
+ ptr to string
+
+--*/
+{
+ UINT typ = bmAttributes & USB_ENDPOINT_TYPE_MASK;
+
+
+ switch( typ) {
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ return "USB_ENDPOINT_TYPE_INTERRUPT";
+
+ case USB_ENDPOINT_TYPE_BULK:
+ return "USB_ENDPOINT_TYPE_BULK";
+
+ case USB_ENDPOINT_TYPE_ISOCHRONOUS:
+ return "USB_ENDPOINT_TYPE_ISOCHRONOUS";
+
+ case USB_ENDPOINT_TYPE_CONTROL:
+ return "USB_ENDPOINT_TYPE_CONTROL";
+
+ default:
+ return "??? UNKNOWN!!";
+ }
+}
+
+
+char *
+usbConfigAttributesString(UCHAR bmAttributes)
+/*++
+Routine Description:
+
+ Called to get ascii string of USB_CONFIGURATION_DESCRIPTOR attributes
+
+Arguments:
+
+ PUSB_CONFIGURATION_DESCRIPTOR->bmAttributes
+
+Return Value:
+
+ ptr to string
+
+--*/
+{
+ UINT typ = bmAttributes & USB_CONFIG_POWERED_MASK;
+
+
+ switch( typ) {
+
+ case USB_CONFIG_BUS_POWERED:
+ return "USB_CONFIG_BUS_POWERED";
+
+ case USB_CONFIG_SELF_POWERED:
+ return "USB_CONFIG_SELF_POWERED";
+
+ case USB_CONFIG_REMOTE_WAKEUP:
+ return "USB_CONFIG_REMOTE_WAKEUP";
+
+
+ default:
+ return "??? UNKNOWN!!";
+ }
+}
+
+
+void
+print_USB_CONFIGURATION_DESCRIPTOR(PUSB_CONFIGURATION_DESCRIPTOR cd)
+/*++
+Routine Description:
+
+ Called to do formatted ascii dump to console of a USB config descriptor
+
+Arguments:
+
+ ptr to USB configuration descriptor
+
+Return Value:
+
+ none
+
+--*/
+{
+ printf("\n===================\nUSB_CONFIGURATION_DESCRIPTOR\n");
+
+ printf(
+ "bLength = 0x%x, decimal %d\n", cd->bLength, cd->bLength
+ );
+
+ printf(
+ "bDescriptorType = 0x%x ( %s )\n", cd->bDescriptorType,
+ usbDescriptorTypeString( cd->bDescriptorType )
+ );
+
+ printf(
+ "wTotalLength = 0x%x, decimal %d\n", cd->wTotalLength, cd->wTotalLength
+ );
+
+ printf(
+ "bNumInterfaces = 0x%x, decimal %d\n", cd->bNumInterfaces, cd->bNumInterfaces
+ );
+
+ printf(
+ "bConfigurationValue = 0x%x, decimal %d\n",
+ cd->bConfigurationValue, cd->bConfigurationValue
+ );
+
+ printf(
+ "iConfiguration = 0x%x, decimal %d\n", cd->iConfiguration, cd->iConfiguration
+ );
+
+ printf(
+ "bmAttributes = 0x%x ( %s )\n", cd->bmAttributes,
+ usbConfigAttributesString( cd->bmAttributes )
+ );
+
+ printf(
+ "MaxPower = 0x%x, decimal %d\n", cd->MaxPower, cd->MaxPower
+ );
+}
+
+
+void
+print_USB_INTERFACE_DESCRIPTOR(PUSB_INTERFACE_DESCRIPTOR id, UINT ix)
+/*++
+Routine Description:
+
+ Called to do formatted ascii dump to console of a USB interface descriptor
+
+Arguments:
+
+ ptr to USB interface descriptor
+
+Return Value:
+
+ none
+
+--*/
+{
+ printf("\n-----------------------------\nUSB_INTERFACE_DESCRIPTOR #%d\n", ix);
+
+
+ printf(
+ "bLength = 0x%x\n", id->bLength
+ );
+
+
+ printf(
+ "bDescriptorType = 0x%x ( %s )\n", id->bDescriptorType,
+ usbDescriptorTypeString( id->bDescriptorType )
+ );
+
+
+ printf(
+ "bInterfaceNumber = 0x%x\n", id->bInterfaceNumber
+ );
+ printf(
+ "bAlternateSetting = 0x%x\n", id->bAlternateSetting
+ );
+ printf(
+ "bNumEndpoints = 0x%x\n", id->bNumEndpoints
+ );
+ printf(
+ "bInterfaceClass = 0x%x\n", id->bInterfaceClass
+ );
+ printf(
+ "bInterfaceSubClass = 0x%x\n", id->bInterfaceSubClass
+ );
+ printf(
+ "bInterfaceProtocol = 0x%x\n", id->bInterfaceProtocol
+ );
+ printf(
+ "bInterface = 0x%x\n", id->iInterface
+ );
+}
+
+
+void
+print_USB_ENDPOINT_DESCRIPTOR(PUSB_ENDPOINT_DESCRIPTOR ed, int i)
+/*++
+Routine Description:
+
+ Called to do formatted ascii dump to console of a USB endpoint descriptor
+
+Arguments:
+
+ ptr to USB endpoint descriptor,
+ index of this endpt in interface desc
+
+Return Value:
+
+ none
+
+--*/
+{
+ printf(
+ "------------------------------\nUSB_ENDPOINT_DESCRIPTOR for Pipe%02d\n", i
+ );
+
+ printf(
+ "bLength = 0x%x\n", ed->bLength
+ );
+
+ printf(
+ "bDescriptorType = 0x%x ( %s )\n", ed->bDescriptorType,
+ usbDescriptorTypeString( ed->bDescriptorType )
+ );
+
+ if ( USB_ENDPOINT_DIRECTION_IN( ed->bEndpointAddress ) ) {
+ printf(
+ "bEndpointAddress= 0x%x ( INPUT )\n", ed->bEndpointAddress
+ );
+ } else {
+ printf(
+ "bEndpointAddress= 0x%x ( OUTPUT )\n", ed->bEndpointAddress
+ );
+ }
+
+ printf(
+ "bmAttributes= 0x%x ( %s )\n", ed->bmAttributes,
+ usbEndPointTypeString ( ed->bmAttributes )
+ );
+
+ printf(
+ "wMaxPacketSize= 0x%x, decimal %d\n", ed->wMaxPacketSize,
+ ed->wMaxPacketSize
+ );
+
+ printf(
+ "bInterval = 0x%x, decimal %d\n", ed->bInterval, ed->bInterval
+ );
+}
+
+
+BOOL
+DumpUsbConfig()
+/*++
+Routine Description:
+
+ Called to do formatted ascii dump to console of USB
+ configuration, interface, and endpoint descriptors.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE or FALSE
+
+--*/
+{
+ HANDLE hDev;
+ UINT success;
+ int siz, nBytes;
+ char buf[256] = {'\0'};
+
+ hDev = OpenDevice(TRUE);
+ if(hDev == INVALID_HANDLE_VALUE)
+ {
+ return FALSE;
+ }
+
+ siz = sizeof(buf);
+
+ success = DeviceIoControl(hDev,
+ IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR,
+ buf,
+ siz,
+ buf,
+ siz,
+ (PULONG) &nBytes,
+ NULL);
+
+ if(success == FALSE) {
+ printf("Ioct - GetConfigDesc failed %d\n", GetLastError());
+ } else {
+
+ ULONG i;
+ UINT j, n;
+ char *pch;
+ PUSB_CONFIGURATION_DESCRIPTOR cd;
+ PUSB_INTERFACE_DESCRIPTOR id;
+ PUSB_ENDPOINT_DESCRIPTOR ed;
+
+ pch = buf;
+ n = 0;
+
+ cd = (PUSB_CONFIGURATION_DESCRIPTOR) pch;
+
+ print_USB_CONFIGURATION_DESCRIPTOR( cd );
+
+ pch += cd->bLength;
+
+ do {
+ id = (PUSB_INTERFACE_DESCRIPTOR) pch;
+
+ print_USB_INTERFACE_DESCRIPTOR(id, n++);
+
+ pch += id->bLength;
+ for (j=0; j<id->bNumEndpoints; j++) {
+
+ ed = (PUSB_ENDPOINT_DESCRIPTOR) pch;
+
+ print_USB_ENDPOINT_DESCRIPTOR(ed,j);
+
+ pch += ed->bLength;
+ }
+ i = (ULONG)(pch - buf);
+
+ } while (i<cd->wTotalLength);
+ }
+
+ CloseHandle(hDev);
+
+ return success;
+
+}
+
diff --git a/usb/umdf2_fx2/exe/osrusbfx2.vcxproj b/usb/umdf2_fx2/exe/osrusbfx2.vcxproj
new file mode 100644
index 00000000..3ac60333
--- /dev/null
+++ b/usb/umdf2_fx2/exe/osrusbfx2.vcxproj
@@ -0,0 +1,181 @@
+<?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>{020DB89E-97F7-43B1-BC5B-BD2A09EB070D}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <SampleGuid>{A62B86BA-B2B1-4059-959F-064A5F9D7C70}</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 />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Desktop</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>Application</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" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <TargetName>osrusbfx2</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <TargetName>osrusbfx2</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <TargetName>osrusbfx2</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <TargetName>osrusbfx2</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);..\inc;..\sys\inc</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="dump.c" />
+ <ClCompile Include="testapp.c" />
+ <ResourceCompile Include="testapp.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 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/umdf2_fx2/exe/osrusbfx2.vcxproj.Filters b/usb/umdf2_fx2/exe/osrusbfx2.vcxproj.Filters
new file mode 100644
index 00000000..39d6f2be
--- /dev/null
+++ b/usb/umdf2_fx2/exe/osrusbfx2.vcxproj.Filters
@@ -0,0 +1,30 @@
+<?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>{104452B2-CFF6-4BAD-8E54-179D97D98EF8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{F8C6B699-E4D1-450D-A1F1-4D3A0670600A}</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>{64683058-E0C9-49C7-996C-E104FFA4D81B}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dump.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="testapp.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="testapp.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/usb/umdf2_fx2/exe/test.cmd b/usb/umdf2_fx2/exe/test.cmd
new file mode 100644
index 00000000..30b18b85
--- /dev/null
+++ b/usb/umdf2_fx2/exe/test.cmd
@@ -0,0 +1,6 @@
+FOR /L %%i IN (0,1,100000) do (
+
+ osrusbfx2.exe -r 512 -w 512 -c 1000000 -v
+
+)
+
diff --git a/usb/umdf2_fx2/exe/testapp.c b/usb/umdf2_fx2/exe/testapp.c
new file mode 100644
index 00000000..ab6f483f
--- /dev/null
+++ b/usb/umdf2_fx2/exe/testapp.c
@@ -0,0 +1,1262 @@
+/*++
+
+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:
+
+ TESTAPP.C
+
+Abstract:
+
+ Console test app for osrusbfx2 driver.
+
+Environment:
+
+ user mode only
+
+--*/
+
+
+#include <DriverSpecs.h>
+_Analysis_mode_(_Analysis_code_type_user_code_)
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "devioctl.h"
+#include "strsafe.h"
+
+#pragma warning(disable:4200) //
+#pragma warning(disable:4201) // nameless struct/union
+#pragma warning(disable:4214) // bit field types other than int
+
+#include <setupapi.h>
+#include <basetyps.h>
+#include "usbdi.h"
+#include "public.h"
+
+#pragma warning(default:4200)
+#pragma warning(default:4201)
+#pragma warning(default:4214)
+
+#define WHILE(a) \
+while(__pragma(warning(disable:4127)) a __pragma(warning(disable:4127)))
+
+#define MAX_DEVPATH_LENGTH 256
+#define NUM_ASYNCH_IO 100
+#define BUFFER_SIZE 1024
+#define READER_TYPE 1
+#define WRITER_TYPE 2
+
+BOOL G_fDumpUsbConfig = FALSE; // flags set in response to console command line switches
+BOOL G_fDumpReadData = FALSE;
+BOOL G_fRead = FALSE;
+BOOL G_fWrite = FALSE;
+BOOL G_fPlayWithDevice = FALSE;
+BOOL G_fPerformAsyncIo = FALSE;
+ULONG G_IterationCount = 1; //count of iterations of the test we are to perform
+ULONG G_WriteLen = 512; // #bytes to write
+ULONG G_ReadLen = 512; // #bytes to read
+
+BOOL
+DumpUsbConfig( // defined in dump.c
+ );
+
+typedef enum _INPUT_FUNCTION {
+ LIGHT_ONE_BAR = 1,
+ CLEAR_ONE_BAR,
+ LIGHT_ALL_BARS,
+ CLEAR_ALL_BARS,
+ GET_BAR_GRAPH_LIGHT_STATE,
+ GET_SWITCH_STATE,
+ GET_SWITCH_STATE_AS_INTERRUPT_MESSAGE,
+ GET_7_SEGEMENT_STATE,
+ SET_7_SEGEMENT_STATE,
+ RESET_DEVICE,
+ REENUMERATE_DEVICE,
+} INPUT_FUNCTION;
+
+_Success_(return)
+BOOL
+GetDevicePath(
+ IN LPGUID InterfaceGuid,
+ _Out_writes_z_(BufLen) PCHAR DevicePath,
+ _In_ size_t BufLen
+ )
+{
+ HDEVINFO HardwareDeviceInfo;
+ SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
+ ULONG Length, RequiredLength = 0;
+ BOOL bResult;
+ HRESULT hr;
+
+ HardwareDeviceInfo = SetupDiGetClassDevs(
+ InterfaceGuid,
+ NULL,
+ NULL,
+ (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+ if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
+ printf("SetupDiGetClassDevs failed!\n");
+ return FALSE;
+ }
+
+ DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+
+ bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
+ 0,
+ InterfaceGuid,
+ 0,
+ &DeviceInterfaceData);
+
+ if (bResult == FALSE) {
+
+ LPVOID lpMsgBuf;
+
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &lpMsgBuf,
+ 0,
+ NULL
+ )) {
+
+ printf("SetupDiEnumDeviceInterfaces failed: %s", (LPSTR)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ return FALSE;
+ }
+
+ SetupDiGetDeviceInterfaceDetail(
+ HardwareDeviceInfo,
+ &DeviceInterfaceData,
+ NULL,
+ 0,
+ &RequiredLength,
+ NULL
+ );
+
+ DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
+ LocalAlloc(LMEM_FIXED, RequiredLength);
+
+ if (DeviceInterfaceDetailData == NULL) {
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ printf("Failed to allocate memory.\n");
+ return FALSE;
+ }
+
+ DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+ Length = RequiredLength;
+
+ bResult = SetupDiGetDeviceInterfaceDetail(
+ HardwareDeviceInfo,
+ &DeviceInterfaceData,
+ DeviceInterfaceDetailData,
+ Length,
+ &RequiredLength,
+ NULL);
+
+ if (bResult == FALSE) {
+
+ LPVOID lpMsgBuf;
+
+ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &lpMsgBuf,
+ 0,
+ NULL)) {
+
+ printf("Error in SetupDiGetDeviceInterfaceDetail: %s\n", (LPSTR)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ }
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ LocalFree(DeviceInterfaceDetailData);
+ return FALSE;
+ }
+
+ hr = StringCchCopy(DevicePath,
+ BufLen,
+ DeviceInterfaceDetailData->DevicePath);
+ if (FAILED(hr)) {
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ LocalFree(DeviceInterfaceDetailData);
+ return FALSE;
+ }
+
+ SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
+ LocalFree(DeviceInterfaceDetailData);
+
+ return TRUE;
+
+}
+
+
+HANDLE
+OpenDevice(
+ _In_ BOOL Synchronous
+ )
+
+/*++
+Routine Description:
+
+ Called by main() to open an instance of our device after obtaining its name
+
+Arguments:
+
+ Synchronous - TRUE, if Device is to be opened for synchronous access.
+ FALSE, otherwise.
+
+Return Value:
+
+ Device handle on success else INVALID_HANDLE_VALUE
+
+--*/
+
+{
+ HANDLE hDev;
+ char completeDeviceName[MAX_DEVPATH_LENGTH];
+
+ if ( !GetDevicePath(
+ (LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
+ completeDeviceName,
+ sizeof(completeDeviceName)) )
+ {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ printf("DeviceName = (%s)\n", completeDeviceName);
+
+ if(Synchronous) {
+ hDev = CreateFile(completeDeviceName,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL, // default security
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ } else {
+
+ hDev = CreateFile(completeDeviceName,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL, // default security
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+ }
+
+ if (hDev == INVALID_HANDLE_VALUE) {
+ printf("Failed to open the device, error - %d", GetLastError());
+ } else {
+ printf("Opened the device successfully.\n");
+ }
+
+ return hDev;
+}
+
+
+
+VOID
+Usage()
+
+/*++
+Routine Description:
+
+ Called by main() to dump usage info to the console when
+ the app is called with no parms or with an invalid parm
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ printf("Usage for osrusbfx2 testapp:\n");
+ printf("-r [n] where n is number of bytes to read\n");
+ printf("-w [n] where n is number of bytes to write\n");
+ printf("-c [n] where n is number of iterations (default = 1)\n");
+ printf("-v verbose -- dumps read data\n");
+ printf("-p to control bar LEDs, seven segment, and dip switch\n");
+ printf("-a to perform asynchronous I/O\n");
+ printf("-u to dump USB configuration and pipe info \n");
+
+ return;
+}
+
+
+void
+Parse(
+ _In_ int argc,
+ _In_reads_(argc) LPSTR *argv
+ )
+
+/*++
+Routine Description:
+
+ Called by main() to parse command line parms
+
+Arguments:
+
+ argc and argv that was passed to main()
+
+Return Value:
+
+ Sets global flags as per user function request
+
+--*/
+
+{
+ int i;
+
+ if ( argc < 2 ) // give usage if invoked with no parms
+ Usage();
+
+ for (i=0; i<argc; i++) {
+ if (argv[i][0] == '-' ||
+ argv[i][0] == '/') {
+ switch(argv[i][1]) {
+ case 'r':
+ case 'R':
+ if (i+1 >= argc) {
+ Usage();
+ exit(1);
+ }
+ else {
+#pragma warning(suppress: 6385)
+ G_ReadLen = atoi(&argv[i+1][0]);
+ G_fRead = TRUE;
+ }
+ i++;
+ break;
+ case 'w':
+ case 'W':
+ if (i+1 >= argc) {
+ Usage();
+ exit(1);
+ }
+ else {
+ G_WriteLen = atoi(&argv[i+1][0]);
+ G_fWrite = TRUE;
+ }
+ i++;
+ break;
+ case 'c':
+ case 'C':
+ if (i+1 >= argc) {
+ Usage();
+ exit(1);
+ }
+ else {
+ G_IterationCount = atoi(&argv[i+1][0]);
+ }
+ i++;
+ break;
+ case 'u':
+ case 'U':
+ G_fDumpUsbConfig = TRUE;
+ break;
+ case 'p':
+ case 'P':
+ G_fPlayWithDevice = TRUE;
+ break;
+ case 'a':
+ case 'A':
+ G_fPerformAsyncIo = TRUE;
+ break;
+ case 'v':
+ case 'V':
+ G_fDumpReadData = TRUE;
+ break;
+ default:
+ Usage();
+ }
+ }
+ }
+}
+
+BOOL
+Compare_Buffs(
+ _In_reads_bytes_(buff1length) char *buff1,
+ _In_ ULONG buff1length,
+ _In_reads_bytes_(buff2length) char *buff2,
+ _In_ ULONG buff2length
+ )
+/*++
+Routine Description:
+
+ Called to verify read and write buffers match for loopback test
+
+Arguments:
+
+ buffers to compare and length
+
+Return Value:
+
+ TRUE if buffers match, else FALSE
+
+--*/
+{
+ int ok = 1;
+
+ if (buff1length != buff2length || memcmp(buff1, buff2, buff1length )) {
+ // Edi, and Esi point to the mismatching char and ecx indicates the
+ // remaining length.
+ ok = 0;
+ }
+
+ return ok;
+}
+
+#define NPERLN 8
+
+VOID
+Dump(
+ UCHAR *b,
+ int len
+)
+
+/*++
+Routine Description:
+
+ Called to do formatted ascii dump to console of the io buffer
+
+Arguments:
+
+ buffer and length
+
+Return Value:
+
+ none
+
+--*/
+
+{
+ ULONG i;
+ ULONG longLen = (ULONG)len / sizeof( ULONG );
+ PULONG pBuf = (PULONG) b;
+
+ // dump an ordinal ULONG for each sizeof(ULONG)'th byte
+ printf("\n****** BEGIN DUMP LEN decimal %d, 0x%x\n", len,len);
+ for (i=0; i<longLen; i++) {
+ printf("%04X ", *pBuf++);
+ if (i % NPERLN == (NPERLN - 1)) {
+ printf("\n");
+ }
+ }
+ if (i % NPERLN != 0) {
+ printf("\n");
+ }
+ printf("\n****** END DUMP LEN decimal %d, 0x%x\n", len,len);
+}
+
+
+BOOL
+PlayWithDevice()
+{
+ HANDLE deviceHandle;
+ DWORD code;
+ ULONG index;
+ INPUT_FUNCTION function;
+ BAR_GRAPH_STATE barGraphState;
+ ULONG bar;
+ SWITCH_STATE switchState;
+ UCHAR sevenSegment = 0;
+ UCHAR i;
+ BOOL result = FALSE;
+
+ deviceHandle = OpenDevice(FALSE);
+
+ if (deviceHandle == INVALID_HANDLE_VALUE) {
+
+ printf("Unable to find any OSR FX2 devices!\n");
+
+ return FALSE;
+
+ }
+
+ //
+ // Infinitely print out the list of choices, ask for input, process
+ // the request
+ //
+ WHILE(TRUE) {
+
+ printf ("\nUSBFX TEST -- Functions:\n\n");
+ printf ("\t1. Light Bar\n");
+ printf ("\t2. Clear Bar\n");
+ printf ("\t3. Light entire Bar graph\n");
+ printf ("\t4. Clear entire Bar graph\n");
+ printf ("\t5. Get bar graph state\n");
+ printf ("\t6. Get Switch state\n");
+ printf ("\t7. Get Switch Interrupt Message\n");
+ printf ("\t8. Get 7 segment state\n");
+ printf ("\t9. Set 7 segment state\n");
+ printf ("\t10. Reset the device\n");
+ printf ("\t11. Reenumerate the device\n");
+ printf ("\n\t0. Exit\n");
+ printf ("\n\tSelection: ");
+
+ if (scanf_s ("%d", &function) <= 0) {
+
+ printf("Error reading input!\n");
+ goto Error;
+
+ }
+
+ switch(function) {
+
+ case LIGHT_ONE_BAR:
+
+ printf("Which Bar (input number 1 thru 8)?\n");
+ if (scanf_s ("%d", &bar) <= 0) {
+
+ printf("Error reading input!\n");
+ goto Error;
+
+ }
+
+ if(bar == 0 || bar > 8){
+ printf("Invalid bar number!\n");
+ goto Error;
+ }
+
+ bar--; // normalize to 0 to 7
+
+ barGraphState.BarsAsUChar = 1 << (UCHAR)bar;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &barGraphState, // Ptr to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ break;
+
+ case CLEAR_ONE_BAR:
+
+
+ printf("Which Bar (input number 1 thru 8)?\n");
+ if (scanf_s ("%d", &bar) <= 0) {
+
+ printf("Error reading input!\n");
+ goto Error;
+
+ }
+
+ if(bar == 0 || bar > 8){
+ printf("Invalid bar number!\n");
+ goto Error;
+ }
+
+ bar--;
+
+ //
+ // Read the current state
+ //
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ &barGraphState, // Ptr to OutBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ if (barGraphState.BarsAsUChar & (1 << bar)) {
+
+ printf("Bar is set...Clearing it\n");
+ barGraphState.BarsAsUChar &= ~(1 << bar);
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &barGraphState, // Ptr to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+
+ }
+
+ } else {
+
+ printf("Bar not set.\n");
+
+ }
+
+ break;
+
+ case LIGHT_ALL_BARS:
+
+ barGraphState.BarsAsUChar = 0xFF;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &barGraphState, // Ptr to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ break;
+
+ case CLEAR_ALL_BARS:
+
+ barGraphState.BarsAsUChar = 0;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
+ &barGraphState, // Ptr to InBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ break;
+
+
+ case GET_BAR_GRAPH_LIGHT_STATE:
+
+ barGraphState.BarsAsUChar = 0;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ &barGraphState, // Ptr to OutBuffer
+ sizeof(BAR_GRAPH_STATE), // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ printf("Bar Graph: \n");
+ printf(" Bar8 is %s\n", barGraphState.Bar8 ? "ON" : "OFF");
+ printf(" Bar7 is %s\n", barGraphState.Bar7 ? "ON" : "OFF");
+ printf(" Bar6 is %s\n", barGraphState.Bar6 ? "ON" : "OFF");
+ printf(" Bar5 is %s\n", barGraphState.Bar5 ? "ON" : "OFF");
+ printf(" Bar4 is %s\n", barGraphState.Bar4 ? "ON" : "OFF");
+ printf(" Bar3 is %s\n", barGraphState.Bar3 ? "ON" : "OFF");
+ printf(" Bar2 is %s\n", barGraphState.Bar2 ? "ON" : "OFF");
+ printf(" Bar1 is %s\n", barGraphState.Bar1 ? "ON" : "OFF");
+
+ break;
+
+ case GET_SWITCH_STATE:
+
+ switchState.SwitchesAsUChar = 0;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_READ_SWITCHES,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ &switchState, // Ptr to OutBuffer
+ sizeof(SWITCH_STATE), // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ printf("Switches: \n");
+ printf(" Switch8 is %s\n", switchState.Switch8 ? "ON" : "OFF");
+ printf(" Switch7 is %s\n", switchState.Switch7 ? "ON" : "OFF");
+ printf(" Switch6 is %s\n", switchState.Switch6 ? "ON" : "OFF");
+ printf(" Switch5 is %s\n", switchState.Switch5 ? "ON" : "OFF");
+ printf(" Switch4 is %s\n", switchState.Switch4 ? "ON" : "OFF");
+ printf(" Switch3 is %s\n", switchState.Switch3 ? "ON" : "OFF");
+ printf(" Switch2 is %s\n", switchState.Switch2 ? "ON" : "OFF");
+ printf(" Switch1 is %s\n", switchState.Switch1 ? "ON" : "OFF");
+
+ break;
+
+ case GET_SWITCH_STATE_AS_INTERRUPT_MESSAGE:
+
+ switchState.SwitchesAsUChar = 0;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ &switchState, // Ptr to OutBuffer
+ sizeof(switchState), // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ printf("Switches: %d\n",index);
+ printf(" Switch8 is %s\n", switchState.Switch8 ? "ON" : "OFF");
+ printf(" Switch7 is %s\n", switchState.Switch7 ? "ON" : "OFF");
+ printf(" Switch6 is %s\n", switchState.Switch6 ? "ON" : "OFF");
+ printf(" Switch5 is %s\n", switchState.Switch5 ? "ON" : "OFF");
+ printf(" Switch4 is %s\n", switchState.Switch4 ? "ON" : "OFF");
+ printf(" Switch3 is %s\n", switchState.Switch3 ? "ON" : "OFF");
+ printf(" Switch2 is %s\n", switchState.Switch2 ? "ON" : "OFF");
+ printf(" Switch1 is %s\n", switchState.Switch1 ? "ON" : "OFF");
+
+ break;
+
+ case GET_7_SEGEMENT_STATE:
+
+ sevenSegment = 0;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ &sevenSegment, // Ptr to OutBuffer
+ sizeof(UCHAR), // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ printf("7 Segment mask: 0x%x\n", sevenSegment);
+ break;
+
+ case SET_7_SEGEMENT_STATE:
+
+ for (i = 0; i < 8; i++) {
+
+ sevenSegment = 1 << i;
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY,
+ &sevenSegment, // Ptr to InBuffer
+ sizeof(UCHAR), // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ 0)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ printf("This is %d\n", i);
+ Sleep(500);
+
+ }
+
+ printf("7 Segment mask: 0x%x\n", sevenSegment);
+ break;
+
+ case RESET_DEVICE:
+
+ printf("Reset the device\n");
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_RESET_DEVICE,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ NULL)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ break;
+
+ case REENUMERATE_DEVICE:
+
+ printf("Re-enumerate the device\n");
+
+ if (!DeviceIoControl(deviceHandle,
+ IOCTL_OSRUSBFX2_REENUMERATE_DEVICE,
+ NULL, // Ptr to InBuffer
+ 0, // Length of InBuffer
+ NULL, // Ptr to OutBuffer
+ 0, // Length of OutBuffer
+ &index, // BytesReturned
+ NULL)) { // Ptr to Overlapped structure
+
+ code = GetLastError();
+
+ printf("DeviceIoControl failed with error 0x%x\n", code);
+
+ goto Error;
+ }
+
+ //
+ // Close the handle to the device and exit out so that
+ // the driver can unload when the device is surprise-removed
+ // and reenumerated.
+ //
+ default:
+
+ result = TRUE;
+ goto Error;
+
+ }
+
+ } // end of while loop
+
+Error:
+
+ CloseHandle(deviceHandle);
+ return result;
+
+}
+
+
+ULONG
+AsyncIo(
+ PVOID ThreadParameter
+ )
+{
+ HANDLE hDevice = INVALID_HANDLE_VALUE;
+ HANDLE hCompletionPort = NULL;
+ OVERLAPPED *pOvList = NULL;
+ PUCHAR buf = NULL;
+ ULONG_PTR i;
+ ULONG ioType = (ULONG)(ULONG_PTR)ThreadParameter;
+ ULONG error;
+
+ hDevice = OpenDevice(FALSE);
+
+ if (hDevice == INVALID_HANDLE_VALUE) {
+ printf("Cannot open device %d\n", GetLastError());
+ goto Error;
+ }
+
+ hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0);
+
+ if (hCompletionPort == NULL) {
+ printf("Cannot open completion port %d \n",GetLastError());
+ goto Error;
+ }
+
+ pOvList = (OVERLAPPED *)malloc(NUM_ASYNCH_IO * sizeof(OVERLAPPED));
+
+ if (pOvList == NULL) {
+ printf("Cannot allocate overlapped array \n");
+ goto Error;
+ }
+
+ buf = (PUCHAR)malloc(NUM_ASYNCH_IO * BUFFER_SIZE);
+
+ if (buf == NULL) {
+ printf("Cannot allocate buffer \n");
+ goto Error;
+ }
+
+ ZeroMemory(pOvList, NUM_ASYNCH_IO * sizeof(OVERLAPPED));
+ ZeroMemory(buf, NUM_ASYNCH_IO * BUFFER_SIZE);
+
+ //
+ // Issue asynch I/O
+ //
+
+ for (i = 0; i < NUM_ASYNCH_IO; i++) {
+ if (ioType == READER_TYPE) {
+ if ( ReadFile( hDevice,
+ buf + (i* BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ &pOvList[i]) == 0) {
+
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf(" %Iu th read failed %d \n",i, GetLastError());
+ goto Error;
+ }
+ }
+
+ } else {
+ if ( WriteFile( hDevice,
+ buf + (i* BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ &pOvList[i]) == 0) {
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf(" %Iu th write failed %d \n",i, GetLastError());
+ goto Error;
+ }
+ }
+ }
+ }
+
+ //
+ // Wait for the I/Os to complete. If one completes then reissue the I/O
+ //
+
+ WHILE (1) {
+ OVERLAPPED *completedOv;
+ ULONG_PTR key;
+ ULONG numberOfBytesTransferred;
+
+ if ( GetQueuedCompletionStatus(hCompletionPort, &numberOfBytesTransferred,
+ &key, &completedOv, INFINITE) == 0) {
+ printf("GetQueuedCompletionStatus failed %d\n", GetLastError());
+ goto Error;
+ }
+
+ //
+ // Read successfully completed. Issue another one.
+ //
+
+ if (ioType == READER_TYPE) {
+
+ i = completedOv - pOvList;
+
+ printf("Number of bytes read by request number %Iu is %d\n",
+ i, numberOfBytesTransferred);
+
+ if ( ReadFile( hDevice,
+ buf + (i * BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ completedOv) == 0) {
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf("%Iu th Read failed %d \n", i, GetLastError());
+ goto Error;
+ }
+ }
+ } else {
+
+ i = completedOv - pOvList;
+
+ printf("Number of bytes written by request number %Iu is %d\n",
+ i, numberOfBytesTransferred);
+
+ if ( WriteFile( hDevice,
+ buf + (i * BUFFER_SIZE),
+ BUFFER_SIZE,
+ NULL,
+ completedOv) == 0) {
+ error = GetLastError();
+ if (error != ERROR_IO_PENDING) {
+ printf("%Iu th write failed %d \n", i, GetLastError());
+ goto Error;
+ }
+ }
+ }
+ }
+
+Error:
+ if (hDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hDevice);
+ }
+
+ if (hCompletionPort) {
+ CloseHandle(hCompletionPort);
+ }
+
+ if (pOvList) {
+ free(pOvList);
+ }
+ if (buf) {
+ free(buf);
+ }
+
+ return 1;
+
+}
+
+
+int
+_cdecl
+main(
+ _In_ int argc,
+ _In_reads_(argc) LPSTR *argv
+ )
+/*++
+Routine Description:
+
+ Entry point to rwbulk.exe
+ Parses cmdline, performs user-requested tests
+
+Arguments:
+
+ argc, argv standard console 'c' app arguments
+
+Return Value:
+
+ Zero
+
+--*/
+
+{
+ char * pinBuf = NULL;
+ char * poutBuf = NULL;
+ ULONG nBytesRead;
+ ULONG nBytesWrite = 0;
+ int ok;
+ int retValue = 0;
+ UINT success;
+ HANDLE hRead = INVALID_HANDLE_VALUE;
+ HANDLE hWrite = INVALID_HANDLE_VALUE;
+ ULONG fail = 0L;
+ ULONG i;
+
+
+ Parse(argc, argv );
+
+ //
+ // dump USB configuation and pipe info
+ //
+ if (G_fDumpUsbConfig) {
+ DumpUsbConfig();
+ }
+
+ if (G_fPlayWithDevice) {
+ PlayWithDevice();
+ goto exit;
+ }
+
+ if (G_fPerformAsyncIo) {
+ HANDLE th1;
+
+ //
+ // Create a reader thread
+ //
+ th1 = CreateThread( NULL, // Default Security Attrib.
+ 0, // Initial Stack Size,
+ AsyncIo, // Thread Func
+ (LPVOID)READER_TYPE,
+ 0, // Creation Flags
+ NULL ); // Don't need the Thread Id.
+
+ if (th1 == NULL) {
+ printf("Couldn't create reader thread - error %d\n", GetLastError());
+ retValue = 1;
+ goto exit;
+ }
+
+ //
+ // Use this thread for peforming write.
+ //
+ AsyncIo((PVOID)WRITER_TYPE);
+
+ goto exit;
+ }
+
+ //
+ // doing a read, write, or both test
+ //
+ if ((G_fRead) || (G_fWrite)) {
+
+ if (G_fRead) {
+ if ( G_fDumpReadData ) { // round size to sizeof ULONG for readable dumping
+ while( G_ReadLen % sizeof( ULONG ) ) {
+ G_ReadLen++;
+ }
+ }
+
+ //
+ // open the output file
+ //
+ hRead = OpenDevice(TRUE);
+ if(hRead == INVALID_HANDLE_VALUE) {
+ retValue = 1;
+ goto exit;
+ }
+
+ pinBuf = malloc(G_ReadLen);
+ }
+
+ if (G_fWrite) {
+ if ( G_fDumpReadData ) { // round size to sizeof ULONG for readable dumping
+ while( G_WriteLen % sizeof( ULONG ) ) {
+ G_WriteLen++;
+ }
+ }
+
+ //
+ // open the output file
+ //
+ hWrite = OpenDevice(TRUE);
+ if(hWrite == INVALID_HANDLE_VALUE) {
+ retValue = 1;
+ goto exit;
+ }
+
+ poutBuf = malloc(G_WriteLen);
+ }
+
+ for (i = 0; i < G_IterationCount; i++) {
+ ULONG j;
+
+ if (G_fWrite && poutBuf && hWrite != INVALID_HANDLE_VALUE) {
+
+ PULONG pOut = (PULONG) poutBuf;
+ ULONG numLongs = G_WriteLen / sizeof( ULONG );
+
+ //
+ // put some data in the output buffer
+ //
+ for (j=0; j<numLongs; j++) {
+ *(pOut+j) = j;
+ }
+
+ //
+ // send the write
+ //
+ success = WriteFile(hWrite, poutBuf, G_WriteLen, &nBytesWrite, NULL);
+ if(success == 0) {
+ printf("WriteFile failed - error %d\n", GetLastError());
+ retValue = 1;
+ goto exit;
+ }
+ printf("Write (%04.4u) : request %06.6u bytes -- %06.6u bytes written\n",
+ i, G_WriteLen, nBytesWrite);
+
+ assert(nBytesWrite == G_WriteLen);
+ }
+
+ if (G_fRead && pinBuf) {
+
+ success = ReadFile(hRead, pinBuf, G_ReadLen, &nBytesRead, NULL);
+ if(success == 0) {
+ printf("ReadFile failed - error %d\n", GetLastError());
+ retValue = 1;
+ goto exit;
+ }
+
+ printf("Read (%04.4u) : request %06.6u bytes -- %06.6u bytes read\n",
+ i, G_ReadLen, nBytesRead);
+
+ if (G_fWrite && poutBuf) {
+
+ //
+ // validate the input buffer against what
+ // we sent to the 82930 (loopback test)
+ //
+ ok = Compare_Buffs(pinBuf, nBytesRead, poutBuf, nBytesWrite);
+
+ if( G_fDumpReadData ) {
+ printf("Dumping read buffer\n");
+ Dump( (PUCHAR) pinBuf, nBytesRead );
+ printf("Dumping write buffer\n");
+ Dump( (PUCHAR) poutBuf, nBytesRead );
+ }
+ assert(ok);
+
+ if(ok != 1) {
+ fail++;
+ }
+
+ assert(G_ReadLen == G_WriteLen);
+ assert(nBytesRead == G_ReadLen);
+ }
+ }
+ }
+
+ }
+
+exit:
+
+ if (pinBuf) {
+ free(pinBuf);
+ }
+
+ if (poutBuf) {
+ free(poutBuf);
+ }
+
+ // close devices if needed
+ if (hRead != INVALID_HANDLE_VALUE) {
+ CloseHandle(hRead);
+ }
+
+ if (hWrite != INVALID_HANDLE_VALUE) {
+ CloseHandle(hWrite);
+ }
+
+ return retValue;
+}
+
+
diff --git a/usb/umdf2_fx2/exe/testapp.rc b/usb/umdf2_fx2/exe/testapp.rc
new file mode 100644
index 00000000..3947204a
--- /dev/null
+++ b/usb/umdf2_fx2/exe/testapp.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "OSRUSBFX2 Bulk & Isoch Read and Write test App"
+#define VER_INTERNALNAME_STR "osrusbfx2.exe"
+#define VER_ORIGINALFILENAME_STR "osrusbfx2.exe"
+
+#include <common.ver>
+
diff --git a/usb/umdf2_fx2/inc/prototypes.h b/usb/umdf2_fx2/inc/prototypes.h
new file mode 100644
index 00000000..cc99cdfe
--- /dev/null
+++ b/usb/umdf2_fx2/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/umdf2_fx2/inc/public.h b/usb/umdf2_fx2/inc/public.h
new file mode 100644
index 00000000..12ddf21f
--- /dev/null
+++ b/usb/umdf2_fx2/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/umdf2_fx2/umdf2_fx2.sln b/usb/umdf2_fx2/umdf2_fx2.sln
new file mode 100644
index 00000000..8f165bef
--- /dev/null
+++ b/usb/umdf2_fx2/umdf2_fx2.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0
+MinimumVisualStudioVersion = 12.0
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Driver", "Driver", "{A3ECF9EF-7A4E-4E3A-8B6C-F28831959DF5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Exe", "Exe", "{1316F001-B1D6-4F04-9298-A553516BACF9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osrusbfx2um", "driver\osrusbfx2um.vcxproj", "{33535CCD-5A39-4FDC-9C3A-796896CE065B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "osrusbfx2", "exe\osrusbfx2.vcxproj", "{020DB89E-97F7-43B1-BC5B-BD2A09EB070D}"
+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
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Debug|Win32.Build.0 = Debug|Win32
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Release|Win32.ActiveCfg = Release|Win32
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Release|Win32.Build.0 = Release|Win32
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Debug|x64.ActiveCfg = Debug|x64
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Debug|x64.Build.0 = Debug|x64
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Release|x64.ActiveCfg = Release|x64
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B}.Release|x64.Build.0 = Release|x64
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Debug|Win32.Build.0 = Debug|Win32
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Release|Win32.ActiveCfg = Release|Win32
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Release|Win32.Build.0 = Release|Win32
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Debug|x64.ActiveCfg = Debug|x64
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Debug|x64.Build.0 = Debug|x64
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Release|x64.ActiveCfg = Release|x64
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {33535CCD-5A39-4FDC-9C3A-796896CE065B} = {A3ECF9EF-7A4E-4E3A-8B6C-F28831959DF5}
+ {020DB89E-97F7-43B1-BC5B-BD2A09EB070D} = {1316F001-B1D6-4F04-9298-A553516BACF9}
+ EndGlobalSection
+EndGlobal