NTSTATUS PciDtfDeviceGetInfo(IN WDFDEVICE Device, IN WDFREQUEST Request) { PCIDTF_DEV_INFO *ReqData; ULONG Value, Length; NTSTATUS Status = STATUS_SUCCESS; __try { Status = WdfRequestRetrieveOutputBuffer(Request, sizeof(PCIDTF_DEV_INFO), (PVOID *) & ReqData, NULL); if (!NT_SUCCESS(Status)) { TRACE_ERR("WdfRequestRetrieveOutputBuffer", Status); __leave; } Status = WdfDeviceQueryProperty(Device, DevicePropertyBusNumber, sizeof(Value), &Value, &Length); if (!NT_SUCCESS(Status)) { TRACE_ERR ("WdfDeviceQueryProperty(DevicePropertyBusNumber)", Status); __leave; } ReqData->bus = (UINT8) Value; Status = WdfDeviceQueryProperty(Device, DevicePropertyAddress, sizeof(Value), &Value, &Length); if (!NT_SUCCESS(Status)) { TRACE_ERR ("WdfDeviceQueryProperty(DevicePropertyAddress)", Status); __leave; } ReqData->devfn = (UINT8) Value; ReqData->reg_count = (int) WdfCollectionGetCount(GetDeviceData(Device)->RegSpaces); TRACE_MSG(TRACE_LEVEL_VERBOSE, TRACE_FLAG_QUEUE, "bus=0x%X, devfn=0x%X, reg_count=%d\n", ReqData->bus, ReqData->devfn, ReqData->reg_count); WdfRequestSetInformation(Request, sizeof(PCIDTF_DEV_INFO)); } __finally { WdfRequestComplete(Request, Status); } return Status; }
VOID FilterEvtDeviceContextCleanup( IN WDFDEVICE Device ) /*++ Routine Description: EvtDeviceRemove event callback must perform any operations that are necessary before the specified device is removed. The framework calls the driver's EvtDeviceRemove callback when the PnP manager sends an IRP_MN_REMOVE_DEVICE request to the driver stack. Arguments: Device - Handle to a framework device object. Return Value: WDF status code --*/ { ULONG count; PAGED_CODE(); KdPrint(("Entered FilterEvtDeviceContextCleanup\n")); WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL); count = WdfCollectionGetCount(FilterDeviceCollection); if(count == 1) { // // We are the last instance. So let us delete the control-device // so that driver can unload when the FilterDevice is deleted. // We absolutely have to do the deletion of control device with // the collection lock acquired because we implicitly use this // lock to protect ControlDevice global variable. We need to make // sure another thread doesn't attempt to create while we are // deleting the device. // FilterDeleteControlDevice(Device); } WdfCollectionRemove(FilterDeviceCollection, Device); WdfWaitLockRelease(FilterDeviceCollectionLock); }
VOID UfxDevice_Reset ( _In_ UFXDEVICE Device ) /*++ Routine Description: Cancels all transfers and disables non-zero endpoints in response to USB reset. Arguments: UfxDevice - UFXDEVICE object representing the device. --*/ { PUFXDEVICE_CONTEXT DeviceContext; PREGISTERS_CONTEXT RegistersContext; ULONG EpIndex; TraceEntry(); DeviceContext = UfxDeviceGetContext(Device); RegistersContext = DeviceGetRegistersContext(DeviceContext->FdoWdfDevice); // // Get EP0 back to setup stage. // TransferReset(WdfCollectionGetFirstItem(DeviceContext->Endpoints)); // // Disable all non-default endpoints // // // #### TODO: Insert code to disable non-default endpoints #### // // // End any transfers on non-default endpoints. // for (EpIndex = 1; EpIndex < WdfCollectionGetCount(DeviceContext->Endpoints); EpIndex++) { TransferReset(WdfCollectionGetItem(DeviceContext->Endpoints, EpIndex)); } TraceExit(); }
WDFCOMMONBUFFER PciDtfCommonBufferFind(IN PDEVICE_DATA DeviceData, IN int ID, IN BOOLEAN Remove) { WDFCOMMONBUFFER CommonBuffer = NULL; ULONG Index, Count; Count = WdfCollectionGetCount(DeviceData->CommonBuffers); for (Index = 0; Index < Count; Index++) { CommonBuffer = (WDFCOMMONBUFFER) WdfCollectionGetItem(DeviceData->CommonBuffers, Index); if (GetCommonBufferData(CommonBuffer)->ID == ID) { if (Remove) WdfCollectionRemoveItem (DeviceData->CommonBuffers, Index); break; } } return Index < Count ? CommonBuffer : NULL; }
NTSTATUS Registry_ReadAllDeviceKeys(__in PDEVICE_CONTEXT deviceContext) { WDFKEY hKey = NULL; NTSTATUS status = STATUS_INVALID_DEVICE_STATE; UNICODE_STRING valueName; WDF_OBJECT_ATTRIBUTES collectionAttributes; WDF_OBJECT_ATTRIBUTES stringAttributes; GUID guidTest = {0}; PAGED_CODE(); if (!deviceContext->WdfDevice) { USBERR("deviceContext->WdfDevice is NULL.\n"); return status; } // The driver sets the PLUGPLAY_REGKEY_DEVICE flag to open the Device // Parameters subkey under the device's hardware key, or it sets the // PLUGPLAY_REGKEY_DRIVER flag to open the driver's software key. If the // PLUGPLAY_REGKEY_CURRENT_HWPROFILE flag is also set, // WdfDeviceOpenRegistryKey opens the copy of the hardware or software key // that is in the current hardware profile. status = WdfDeviceOpenRegistryKey(deviceContext->WdfDevice, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &hKey); if (!NT_SUCCESS (status)) { USBERR("WdfDeviceOpenRegistryKey failed.\n"); hKey = NULL; return status; } ////////////////////////////////////////////////////////////////////////// // Read the device interface guids from the registry. // These are set in the inf files [Device_AddReg] group. // WDF_OBJECT_ATTRIBUTES_INIT(&collectionAttributes); collectionAttributes.ParentObject = deviceContext->WdfDevice; status = WdfCollectionCreate(&collectionAttributes, &deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs); if (!NT_SUCCESS(status)) { USBERR("collection object could not be allocated. status=%Xh", status); goto Done; } WDF_OBJECT_ATTRIBUTES_INIT(&stringAttributes); stringAttributes.ParentObject = deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs; RtlInitUnicodeString(&valueName, L"DeviceInterfaceGUIDs"); status = WdfRegistryQueryMultiString(hKey, &valueName, &stringAttributes, deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs); if (NT_SUCCESS(status)) { ULONG guidCount = WdfCollectionGetCount(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs); ULONG guidIndex; WDFSTRING wdfGuidString; BOOLEAN removeGuidFromCollection; USBMSG("Found %u DeviceInterfaceGUIDs strings.", guidCount); for (guidIndex = 0; guidIndex < guidCount; guidIndex++) { removeGuidFromCollection = TRUE; wdfGuidString = (WDFSTRING)WdfCollectionGetItem(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs, guidIndex); status = GUIDFromWdfString(wdfGuidString, &guidTest); if (!NT_SUCCESS(status)) { USBERR("removing invalid DeviceInterfaceGUID string at index %u\n", guidIndex); } else { if (IsEqualGUID(&guidTest, &Libusb0DeviceGuid)) { USBWRN("libusb0 device DeviceInterfaceGUID found. skippng..\n"); } else if (IsEqualGUID(&guidTest, &Libusb0FilterGuid)) { USBWRN("libusb0 filter DeviceInterfaceGUID found. skippng..\n"); } else if (IsEqualGUID(&guidTest, &LibusbKDeviceGuid)) { USBWRN("libusbK default device DeviceInterfaceGUID found. skippng..\n"); } else { removeGuidFromCollection = FALSE; } } if (removeGuidFromCollection) { WdfCollectionRemoveItem(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs, guidIndex); guidIndex--; guidCount--; } } } else { USBWRN("DeviceInterfaceGUIDs registry key does not exist.\n" " Ensure the DeviceInterfaceGUIDs key has been properly set in the .inf and re-install the device.\n\n"); } if (WdfCollectionGetCount(deviceContext->DeviceRegSettings.DeviceInterfaceGUIDs) == 0) { status = AddDefaultDeviceInterfaceGUID(deviceContext); if (!NT_SUCCESS(status)) { goto Done; } } ////////////////////////////////////////////////////////////////////////// // Read the device power policy settings (if any). // These are set in the inf files [Device_AddReg] group. // GetDeviceRegSettingKey(DeviceIdleEnabled, FALSE); GetDeviceRegSettingKey(DeviceIdleIgnoreWakeEnable, FALSE); GetDeviceRegSettingKey(UserSetDeviceIdleEnabled, FALSE); GetDeviceRegSettingKey(DefaultIdleState, FALSE); GetDeviceRegSettingKey(DefaultIdleTimeout, 5000); GetDeviceRegSettingKey(SystemWakeEnabled, FALSE); status = STATUS_SUCCESS; Done: if (hKey) { WdfRegistryClose(hKey); hKey = NULL; } return status; }
VOID FilterEvtIoDeviceControl( 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 --*/ { ULONG i; ULONG noItems; WDFDEVICE hFilterDevice; PFILTER_EXTENSION filterExt; UNREFERENCED_PARAMETER(Queue); UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(IoControlCode); PAGED_CODE(); KdPrint(("Ioctl recieved into filter control object.\n")); WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL); noItems = WdfCollectionGetCount(FilterDeviceCollection); for(i=0; i<noItems ; i++) { hFilterDevice = WdfCollectionGetItem(FilterDeviceCollection, i); filterExt = FilterGetData(hFilterDevice); KdPrint(("Serial No: %d\n", filterExt->SerialNo)); } WdfWaitLockRelease(FilterDeviceCollectionLock); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 0); }
NTSTATUS FilterCreateControlDevice( WDFDEVICE Device ) /*++ Routine Description: This routine is called to create a control deviceobject so that application can talk to the filter driver directly instead of going through the entire device stack. This kind of control device object is useful if the filter driver is underneath another driver which prevents ioctls not known to it or if the driver's dispatch routine is owned by some other (port/class) driver and it doesn't allow any custom ioctls. NOTE: Since the control device is global to the driver and accessible to all instances of the device this filter is attached to, we create only once when the first instance of the device is started and delete it when the last instance gets removed. Arguments: Device - Handle to a filter device object. Return Value: WDF status code --*/ { PWDFDEVICE_INIT pInit = NULL; WDFDEVICE controlDevice = NULL; WDF_OBJECT_ATTRIBUTES controlAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; BOOLEAN bCreate = FALSE; NTSTATUS status; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; PAGED_CODE(); // // First find out whether any ControlDevice has been created. If the // collection has more than one device then we know somebody has already // created or in the process of creating the device. // WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL); if(WdfCollectionGetCount(FilterDeviceCollection) == 1) { bCreate = TRUE; } WdfWaitLockRelease(FilterDeviceCollectionLock); if(!bCreate) { // // Control device is already created. So return success. // return STATUS_SUCCESS; } KdPrint(("Creating Control Device\n")); // // // In order to create a control device, we first need to allocate a // WDFDEVICE_INIT structure and set all properties. // pInit = WdfControlDeviceInitAllocate( WdfDeviceGetDriver(Device), &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R ); if (pInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } // // Set exclusive to false so that more than one app can talk to the // control device simultaneously. // WdfDeviceInitSetExclusive(pInit, FALSE); status = WdfDeviceInitAssignName(pInit, &ntDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Specify the size of device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&controlAttributes, CONTROL_DEVICE_EXTENSION); status = WdfDeviceCreate(&pInit, &controlAttributes, &controlDevice); if (!NT_SUCCESS(status)) { goto Error; } // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { goto Error; } // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControl; // // Framework by default creates non-power managed queues for // filter drivers. // status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { goto Error; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); ControlDevice = controlDevice; return STATUS_SUCCESS; Error: if (pInit != NULL) { WdfDeviceInitFree(pInit); } if (controlDevice != NULL) { // // Release the reference on the newly created object, since // we couldn't initialize it. // WdfObjectDelete(controlDevice); controlDevice = NULL; } return status; }
VOID UfxDevice_EvtDeviceUsbStateChange ( _In_ UFXDEVICE UfxDevice, _In_ USBFN_DEVICE_STATE NewState ) /*++ Routine Description: EvtDeviceUsbStateChange handler for the UFXDEVICE object. Arguments: UfxDevice - UFXDEVICE object representing the device. NewState - The new device state. --*/ { NTSTATUS Status; PUFXDEVICE_CONTEXT Context; PCONTROLLER_CONTEXT ControllerContext; ULONG EpIndex; USBFN_DEVICE_STATE OldState; PAGED_CODE(); TraceEntry(); Context = UfxDeviceGetContext(UfxDevice); ControllerContext = DeviceGetControllerContext(Context->FdoWdfDevice); OldState = Context->UsbState; TraceInformation("New STATE: %d", NewState); Status = UfxDeviceStopOrResumeIdle(UfxDevice, NewState, Context->UsbPort); LOG_NT_MSG(Status, "Failed to stop or resume idle"); WdfWaitLockAcquire(ControllerContext->InitializeDefaultEndpointLock, NULL); if (ControllerContext->InitializeDefaultEndpoint == TRUE) { // // Reset endpoint 0. This is the last part of soft reset, which was postponed // until now, since we need to make sure EP0 is created by UFX. // DeviceInitializeDefaultEndpoint(Context->FdoWdfDevice); ControllerContext->InitializeDefaultEndpoint = FALSE; } WdfWaitLockRelease(ControllerContext->InitializeDefaultEndpointLock); if (NewState == UsbfnDeviceStateConfigured && OldState != UsbfnDeviceStateSuspended) { for (EpIndex = 1; EpIndex < WdfCollectionGetCount(Context->Endpoints); EpIndex++) { UfxEndpointConfigure(WdfCollectionGetItem(Context->Endpoints, EpIndex)); } // // #### TODO: Insert code to allow the controller to accept U1/U2, if supported #### // } if (NewState == UsbfnDeviceStateDetached) { KeSetEvent(&ControllerContext->DetachEvent, IO_NO_INCREMENT, FALSE); } UfxDeviceEventComplete(UfxDevice, STATUS_SUCCESS); TraceExit(); }
NTSTATUS Ucm_CreateConnectors ( _In_ PPPM_CONTEXT PpmCtx ) /*++ Routine Description: Create connector objects and register them with UCM. Arguments: PpmCtx - Platform policy manager context object. --*/ { NTSTATUS status; WDFDEVICE device; UCSI_GET_CAPABILITY_IN caps; UCSI_GET_CONNECTOR_CAPABILITY_IN connCaps; UCM_CONNECTOR_CONFIG connConfig; UCM_CONNECTOR_TYPEC_CONFIG typeCConfig; UCM_CONNECTOR_PD_CONFIG pdConfig; ULONG supportedOperatingModes; ULONG supportedPowerSourcingCapabilities; ULONG supportedPdPowerRoles; PPPM_CONNECTOR connector; ULONG connectorCount; WDF_OBJECT_ATTRIBUTES attributes; PPPM_UCM_CONNECTOR_CONTEXT connectorCtx; CONNECTOR_INDEX i; UNREFERENCED_PARAMETER(PpmCtx); PAGED_CODE(); TRACE_FUNC_ENTRY(TRACE_FLAG_UCMNOTIFICATIONS); device = Context_GetWdfDevice(PpmCtx); status = Ppm_GetCapability(PpmCtx, &caps); if (!NT_SUCCESS(status)) { goto Exit; } TRACE_INFO(TRACE_FLAG_UCMNOTIFICATIONS, "[Device: 0x%p] PPM optional features: 0x%x", device, caps.OptionalFeatures); connectorCount = WdfCollectionGetCount(PpmCtx->Connectors); if (connectorCount != caps.bNumConnectors) { status = STATUS_DEVICE_PROTOCOL_ERROR; TRACE_ERROR(TRACE_FLAG_UCMNOTIFICATIONS, "[Device: 0x%p] Connector count mismatch. ACPI reported %lu, UCSI reported %lu", device, connectorCount, caps.bNumConnectors); goto Exit; } for (i = 1; i <= connectorCount; ++i) { status = Ppm_GetConnectorCapability(PpmCtx, i, &connCaps); if (!NT_SUCCESS(status)) { goto Exit; } connector = Ppm_GetConnector(PpmCtx, i); supportedOperatingModes = (connCaps.OperationMode.DfpOnly ? UcmTypeCOperatingModeDfp : 0) | (connCaps.OperationMode.UfpOnly ? UcmTypeCOperatingModeUfp : 0) | (connCaps.OperationMode.Drp ? UcmTypeCOperatingModeDrp : 0); if (connCaps.Provider) { supportedPowerSourcingCapabilities = UcmTypeCCurrentDefaultUsb | UcmTypeCCurrent1500mA | UcmTypeCCurrent3000mA; } else { supportedPowerSourcingCapabilities = 0; } // // Assemble the Type-C and PD configuration for UCM. // UCM_CONNECTOR_CONFIG_INIT(&connConfig, connector->Id); UCM_CONNECTOR_TYPEC_CONFIG_INIT(&typeCConfig, supportedOperatingModes, supportedPowerSourcingCapabilities); typeCConfig.EvtSetDataRole = Ucm_EvtConnectorSetDataRole; typeCConfig.AudioAccessoryCapable = connCaps.OperationMode.AudioAccessoryMode; supportedPdPowerRoles = (connCaps.Provider ? UcmPowerRoleSource : 0) | (connCaps.Consumer ? UcmPowerRoleSink : 0); UCM_CONNECTOR_PD_CONFIG_INIT(&pdConfig, supportedPdPowerRoles); pdConfig.EvtSetPowerRole = Ucm_EvtConnectorSetPowerRole; connConfig.TypeCConfig = &typeCConfig; connConfig.PdConfig = &pdConfig; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, PPM_UCM_CONNECTOR_CONTEXT); // // Create the UCM connector object. // status = UcmConnectorCreate(device, &connConfig, &attributes, &connector->Handle); if (!NT_SUCCESS(status)) { TRACE_ERROR(TRACE_FLAG_UCMNOTIFICATIONS, "[Device: 0x%p] UcmConnectorCreate failed - %!STATUS!", device, status); goto Exit; } connectorCtx = PpmUcmConnector_GetContext(connector->Handle); connectorCtx->PpmConnector = connector; } Exit: TRACE_FUNC_EXIT(TRACE_FLAG_UCMNOTIFICATIONS); return status; }