Sample Code
Windows Driver Samples/ PortIO Sample Driver/ C++/ sys/ device.c/
/*++ Copyright (c) Microsoft Module Name: device.c - Device handling events for example driver. Abstract: This is a C version of a very simple sample driver that illustrates how to use the driver framework and demonstrates best practices. --*/ #include "driver.h" #ifdef ALLOC_PRAGMA #pragma alloc_text (PAGE, PortIODeviceCreate) #pragma alloc_text (PAGE, PortIOEvtDevicePrepareHardware) #pragma alloc_text (PAGE, PortIOEvtDeviceReleaseHardware) #endif NTSTATUS PortIODeviceCreate( PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInit - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; PDEVICE_CONTEXT deviceContext; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDFDEVICE device; NTSTATUS status; UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; WDF_FILEOBJECT_CONFIG fileConfig; PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Register pnp/power callbacks so that we can start and stop the timer as // the device gets started and stopped. // pnpPowerCallbacks.EvtDevicePrepareHardware = PortIOEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PortIOEvtDeviceReleaseHardware; // // Register the PnP and power callbacks. Power policy related callbacks will // be registered later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK // not interested in Cleanup ); // Let the framework complete create and close fileConfig.AutoForwardCleanupClose = WdfFalse; WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // // Create a named deviceobject so that legacy applications can talk to us. // Since we are naming the object, we wouldn't able to install multiple // instance of this driver. Please note that as per PNP guidelines, we // should not name the FDO or create symbolic links. We are doing it because // we have a legacy APP that doesn't know how to open an interface. // RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME); status = WdfDeviceInitAssignName(DeviceInit,&ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, GPD_TYPE); // // Call this if the device is not holding a pagefile // crashdump file or hibernate file. // WdfDeviceInitSetPowerPageable(DeviceInit); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the // device.h header file. This function will do the type checking and return // the device context. If you pass a wrong object handle // it will return NULL and assert if run under framework verifier mode. // deviceContext = PortIOGetDeviceContext(device); // // This values is based on the hardware design. // I'm assuming the address is in I/O space for our hardware. // Refer http://support.microsoft.com/default.aspx?scid=kb;en-us;Q323595 // for more info. // deviceContext-> PortMemoryType = 1; // // Create a device interface so that application can find and talk // to us. // RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); status = WdfDeviceCreateSymbolicLink( device, &win32DeviceName); if (!NT_SUCCESS(status)) { return status; } // // Initialize the I/O Package and any Queues // status = PortIOQueueInitialize(device); return status; } NTSTATUS PortIOEvtDevicePrepareHardware( _In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesRaw, _In_ WDFCMRESLIST ResourcesTranslated ) /*++ Routine Description: This event is called by the Framework when the device is started or restarted after a suspend operation. Arguments: Device - Handle to a framework device object. Return Value: NTSTATUS - Failures will result in the device stack being torn down. --*/ { ULONG i; PCM_PARTIAL_RESOURCE_DESCRIPTOR desc; PCM_PARTIAL_RESOURCE_DESCRIPTOR descTranslated; PDEVICE_CONTEXT deviceContext = NULL; NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); if ((NULL == ResourcesRaw) || (NULL == ResourcesTranslated)){ return STATUS_DEVICE_CONFIGURATION_ERROR; } deviceContext = PortIOGetDeviceContext(Device); for (i=0; i < WdfCmResourceListGetCount(ResourcesRaw); i++) { desc = WdfCmResourceListGetDescriptor(ResourcesRaw, i); descTranslated = WdfCmResourceListGetDescriptor(ResourcesTranslated, i); switch(desc ->Type) { case CmResourceTypePort: switch(descTranslated -> Type) { case CmResourceTypePort: deviceContext -> PortWasMapped = FALSE; deviceContext -> PortBase = ULongToPtr(descTranslated->u.Port.Start.LowPart); deviceContext -> PortCount = descTranslated ->u.Port.Length; KdPrint(("Resource Translated Port: (%x) Length: (%d)\n", descTranslated->u.Port.Start.LowPart, descTranslated->u.Port.Length)); break; case CmResourceTypeMemory: // // Map the memory // deviceContext-> PortBase = (PVOID) MmMapIoSpace(descTranslated->u.Memory.Start, descTranslated->u.Memory.Length, MmNonCached); deviceContext-> PortCount = descTranslated->u.Memory.Length; deviceContext-> PortWasMapped = TRUE; KdPrint(("Resource Translated Memory: (%x) Length: (%d)\n", descTranslated->u.Memory.Start.LowPart, descTranslated->u.Memory.Length)); break; default: KdPrint(("Unhandled resource_type (0x%x)\n", descTranslated->Type)); status = STATUS_UNSUCCESSFUL; ASSERTMSG("Unhandled resource_type in start request\n", FALSE); } break; case CmResourceTypeMemory: deviceContext-> PortBase = (PVOID) MmMapIoSpace (descTranslated->u.Memory.Start, descTranslated->u.Memory.Length, MmNonCached); deviceContext-> PortCount = descTranslated->u.Memory.Length; deviceContext-> PortWasMapped = TRUE; KdPrint(("Resource Translated Memory: (%x) Length: (%d)\n", descTranslated->u.Memory.Start.LowPart, descTranslated->u.Memory.Length)); break; case CmResourceTypeInterrupt: default: KdPrint(("Unhandled resource type (0x%x)\n", desc->Type)); status = STATUS_UNSUCCESSFUL; break; } } return status; } NTSTATUS PortIOEvtDeviceReleaseHardware( _In_ WDFDEVICE Device, _In_ WDFCMRESLIST ResourcesTranslated ) /*++ Routine Description: s Arguments: Device - Handle to a framework device object. Return Value: NTSTATUS - The driver is not allowed to fail this function. If it does, the device stack will be torn down. --*/ { PDEVICE_CONTEXT deviceContext = NULL; UNREFERENCED_PARAMETER(ResourcesTranslated); deviceContext = PortIOGetDeviceContext(Device); PAGED_CODE(); // // We received query-remove earlier so free up resources. // if (deviceContext->PortWasMapped){ MmUnmapIoSpace(deviceContext->PortBase, deviceContext->PortCount); deviceContext->PortWasMapped = FALSE; } return STATUS_SUCCESS; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials