/*++
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:
Bulk USB device driver for Intel 82930 USB test board
Plug and Play module. This file contains routines to handle pnp requests.
Environment:
Kernel mode
--*/
#include "private.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, UsbSamp_EvtDeviceAdd)
#pragma alloc_text(PAGE, UsbSamp_EvtDevicePrepareHardware)
#pragma alloc_text(PAGE, UsbSamp_EvtDeviceContextCleanup)
#pragma alloc_text(PAGE, ReadAndSelectDescriptors)
#pragma alloc_text(PAGE, ConfigureDevice)
#pragma alloc_text(PAGE, SelectInterfaces)
#pragma alloc_text(PAGE, SetPowerPolicy)
#pragma alloc_text(PAGE, AbortPipes)
#pragma alloc_text(PAGE, ReadFdoRegistryKeyValue)
#pragma alloc_text(PAGE, RetrieveDeviceInformation)
#pragma alloc_text(PAGE, UsbSamp_ValidateConfigurationDescriptor)
#if (NTDDI_VERSION >= NTDDI_WIN8)
#pragma alloc_text(PAGE, UsbSamp_EvtPipeContextCleanup)
#pragma alloc_text(PAGE, InitializePipeContextForSuperSpeedDevice)
#pragma alloc_text(PAGE, GetEndpointDescriptorForEndpointAddress)
#pragma alloc_text(PAGE, InitializePipeContextForSuperSpeedIsochPipe)
#endif
#pragma alloc_text(PAGE, InitializePipeContextForHighSpeedDevice)
#pragma alloc_text(PAGE, InitializePipeContextForFullSpeedDevice)
#endif
NTSTATUS
UsbSamp_EvtDeviceAdd(
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_FILEOBJECT_CONFIG fileConfig;
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;
ULONG maximumTransferSize;
UNREFERENCED_PARAMETER(Driver);
UsbSamp_DbgPrint (3, ("UsbSamp_EvtDeviceAdd routine\n"));
PAGED_CODE();
//
// 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);
pnpPowerCallbacks.EvtDevicePrepareHardware = UsbSamp_EvtDevicePrepareHardware;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
//
// Initialize the request attributes to specify the context size and type
// for every request created by framework for this device.
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);
WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes);
//
// Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the
// framework whether you are interested in handle Create, Close and
// Cleanup requests that gets genereate when an application or another
// kernel component opens an handle to the device. If you don't register
// the framework default behaviour would be complete these requests
// with STATUS_SUCCESS. A driver might be interested in registering these
// events if it wants to do security validation and also wants to maintain
// per handle (fileobject) context.
//
WDF_FILEOBJECT_CONFIG_INIT(
&fileConfig,
UsbSamp_EvtDeviceFileCreate,
WDF_NO_EVENT_CALLBACK,
WDF_NO_EVENT_CALLBACK
);
//
// Specify a context for FileObject. If you register FILE_EVENT callbacks,
// the framework by default creates a framework FILEOBJECT corresponding
// to the WDM fileobject. If you want to track any per handle context,
// use the context for FileObject. Driver that typically use FsContext
// field should instead use Framework FileObject context.
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FILE_CONTEXT);
WdfDeviceInitSetFileObjectConfig(DeviceInit,
&fileConfig,
&attributes);
#if !defined(BUFFERED_READ_WRITE)
//
// I/O type is Buffered by default. We want to do direct I/O for Reads
// and Writes so set it explicitly. Please note that this sample
// can do isoch transfer only if the io type is directio.
//
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
#endif
//
// 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);
attributes.EvtCleanupCallback = UsbSamp_EvtDeviceContextCleanup;
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status)) {
UsbSamp_DbgPrint(1, ("WdfDeviceCreate failed with Status code 0x%x\n", status));
return status;
}
//
// 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 MaximumTransferSize from registry
//
maximumTransferSize = 0;
ReadFdoRegistryKeyValue(Driver,
L"MaximumTransferSize",
&maximumTransferSize);
if (maximumTransferSize){
pDevContext->MaximumTransferSize = maximumTransferSize;
}
else {
pDevContext->MaximumTransferSize = DEFAULT_REGISTRY_TRANSFER_SIZE;
}
//
// Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
// that you don't get the popup in usermode (on Win2K) when you surprise
// remove the device.
//
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
pnpCaps.SurpriseRemovalOK = WdfTrue;
WdfDeviceSetPnpCapabilities(device, &pnpCaps);
//
// Register I/O callbacks to tell the framework that you are interested
// in handling WdfRequestTypeRead, WdfRequestTypeWrite, and
// IRP_MJ_DEVICE_CONTROL requests.
// WdfIoQueueDispatchParallel means that we are capable of handling
// all the I/O request simultaneously and we are responsible for protecting
// data that could be accessed by these callbacks simultaneously.
// This queue will be, by default, automanaged by the framework with
// respect to PNP and Power events. That is, framework will take care
// of queuing, failing, dispatching incoming requests based on the current
// pnp/power state of the device.
//
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoRead = UsbSamp_EvtIoRead;
ioQueueConfig.EvtIoWrite = UsbSamp_EvtIoWrite;
ioQueueConfig.EvtIoDeviceControl = UsbSamp_EvtIoDeviceControl;
ioQueueConfig.EvtIoStop = UsbSamp_Evt