Esempio n. 1
1
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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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();
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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);
}
Esempio n. 7
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;
}
Esempio n. 8
0
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;
}