Sample Code
Windows Driver Samples/ Toaster Sample Driver/ C++/ kmdf/ bus/ static/ buspdo.c/
/*++ Copyright (c) Microsoft Corporation All Rights Reserved Module Name: BusPdo.c Abstract: This module handles plug & play calls for the child device (PDO). Environment: kernel mode only --*/ #include "busenum.h" ULONG BusEnumDebugLevel; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, Bus_CreatePdo) #endif #define MAX_ID_LEN 80 NTSTATUS Bus_CreatePdo( _In_ WDFDEVICE Device, _In_ PWSTR HardwareIds, _In_ ULONG SerialNo ) /*++ Routine Description: This routine creates and initialize a PDO. Arguments: Return Value: NT Status code. --*/ { NTSTATUS status; PWDFDEVICE_INIT pDeviceInit = NULL; PPDO_DEVICE_DATA pdoData = NULL; WDFDEVICE hChild = NULL; WDF_QUERY_INTERFACE_CONFIG qiConfig; WDF_OBJECT_ATTRIBUTES pdoAttributes; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_DEVICE_POWER_CAPABILITIES powerCaps; TOASTER_INTERFACE_STANDARD ToasterInterface; DECLARE_CONST_UNICODE_STRING(compatId, BUSENUM_COMPATIBLE_IDS); DECLARE_CONST_UNICODE_STRING(deviceLocation, L"Toaster Bus 0"); UNICODE_STRING deviceId; DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); KdPrint(("BusEnum: Entered Bus_CreatePdo\n")); PAGED_CODE(); // // Allocate a WDFDEVICE_INIT structure and set the properties // so that we can create a device object for the child. // pDeviceInit = WdfPdoInitAllocate(Device); if (pDeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } // // Set DeviceType // WdfDeviceInitSetDeviceType(pDeviceInit, FILE_DEVICE_BUS_EXTENDER); // // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId // RtlInitUnicodeString(&deviceId,HardwareIds); status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Note same string is used to initialize hardware id too // status = WdfPdoInitAddHardwareID(pDeviceInit, &deviceId); if (!NT_SUCCESS(status)) { goto Cleanup; } status = WdfPdoInitAddCompatibleID(pDeviceInit, &compatId); if (!NT_SUCCESS(status)) { goto Cleanup; } status = RtlUnicodeStringPrintf(&buffer, L"%02d", SerialNo); if (!NT_SUCCESS(status)) { goto Cleanup; } status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Provide a description about the device. This text is usually read from // the device. In the case of USB device, this text comes from the string // descriptor. This text is displayed momentarily by the PnP manager while // it's looking for a matching INF. If it finds one, it uses the Device // Description from the INF file or the friendly name created by // coinstallers to display in the device manager. FriendlyName takes // precedence over the DeviceDesc from the INF file. // status = RtlUnicodeStringPrintf(&buffer,L"Microsoft_Eliyas_Toaster_%02d", SerialNo ); if (!NT_SUCCESS(status)) { goto Cleanup; } // // You can call WdfPdoInitAddDeviceText multiple times, adding device // text for multiple locales. When the system displays the text, it // chooses the text that matches the current locale, if available. // Otherwise it will use the string for the default locale. // The driver can specify the driver's default locale by calling // WdfPdoInitSetDefaultLocale. // status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x409); if (!NT_SUCCESS(status)) { goto Cleanup; } WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // // Initialize the attributes to specify the size of PDO device extension. // All the state information private to the PDO will be tracked here. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA); status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Once the device is created successfully, framework frees the // DeviceInit memory and sets the pDeviceInit to NULL. So don't // call any WdfDeviceInit functions after that. // // Get the device context. // pdoData = PdoGetData(hChild); pdoData->SerialNo = SerialNo; // // Set some properties for the child device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.Removable = WdfTrue; pnpCaps.EjectSupported = WdfTrue; pnpCaps.SurpriseRemovalOK = WdfTrue; pnpCaps.Address = SerialNo; pnpCaps.UINumber = SerialNo; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps); powerCaps.DeviceD1 = WdfTrue; powerCaps.WakeFromD1 = WdfTrue; powerCaps.DeviceWake = PowerDeviceD1; powerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD0; powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1; powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD3; powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD3; powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3; powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3; WdfDeviceSetPowerCapabilities(hChild, &powerCaps); // // Create a custom interface so that other drivers can // query (IRP_MN_QUERY_INTERFACE) and use our callbacks directly. // RtlZeroMemory(&ToasterInterface, sizeof(ToasterInterface)); ToasterInterface.InterfaceHeader.Size = sizeof(ToasterInterface); ToasterInterface.InterfaceHeader.Version = 1; ToasterInterface.InterfaceHeader.Context = (PVOID) hChild; // // Let the framework handle reference counting. // ToasterInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; ToasterInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; ToasterInterface.GetCrispinessLevel = Bus_GetCrispinessLevel; ToasterInterface.SetCrispinessLevel = Bus_SetCrispinessLevel; ToasterInterface.IsSafetyLockEnabled = Bus_IsSafetyLockEnabled; WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE) &ToasterInterface, &GUID_TOASTER_INTERFACE_STANDARD, NULL); // // If you have multiple interfaces, you can call WdfDeviceAddQueryInterface // multiple times to add additional interfaces. // status = WdfDeviceAddQueryInterface(hChild, &qiConfig); if (!NT_SUCCESS(status)) { goto Cleanup; } // // Add this device to the FDO's collection of children. // After the child device is added to the static collection successfully, // driver must call WdfPdoMarkMissing to get the device deleted. It // shouldn't delete the child device directly by calling WdfObjectDelete. // status = WdfFdoAddStaticChild(Device, hChild); if (!NT_SUCCESS(status)) { goto Cleanup; } return status; Cleanup: KdPrint(("BusEnum: Bus_CreatePdo failed %x\n", status)); // // Call WdfDeviceInitFree if you encounter an error before the // device is created. Once the device is created, framework // NULLs the pDeviceInit value. // if (pDeviceInit != NULL) { WdfDeviceInitFree(pDeviceInit); } if(hChild) { WdfObjectDelete(hChild); } return status; } BOOLEAN Bus_GetCrispinessLevel( IN WDFDEVICE ChildDevice, OUT PUCHAR Level ) /*++ Routine Description: This routine gets the current crispiness level of the toaster. Arguments: Context pointer to PDO device extension Level crispiness level of the device Return Value: TRUE or FALSE --*/ { UNREFERENCED_PARAMETER(ChildDevice); // // Validate the context to see if it's really a pointer // to PDO's device extension. You can store some kind // of signature in the PDO for this purpose // KdPrint(("BusEnum: GetCrispnessLevel\n")); *Level = 10; return TRUE; } BOOLEAN Bus_SetCrispinessLevel( IN WDFDEVICE ChildDevice, IN UCHAR Level ) /*++ Routine Description: This routine sets the current crispiness level of the toaster. Arguments: Context pointer to PDO device extension Level crispiness level of the device Return Value: TRUE or FALSE --*/ { UNREFERENCED_PARAMETER(ChildDevice); UNREFERENCED_PARAMETER(Level); KdPrint(("BusEnum: SetCrispnessLevel\n")); return TRUE; } BOOLEAN Bus_IsSafetyLockEnabled( IN WDFDEVICE ChildDevice ) /*++ Routine Description: Routine to check whether safety lock is enabled Arguments: Context pointer to PDO device extension Return Value: TRUE or FALSE --*/ { UNREFERENCED_PARAMETER(ChildDevice); KdPrint(("BusEnum: IsSafetyLockEnabled\n")); return TRUE; }
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