// This callback is called when the simulator wait time has expired and the simulator
// is ready to switch to the next sample. The callback updates the sample index and 
// schedules the next wake up time.
VOID
HardwareSimulator::OnTimerExpire(
    _In_ WDFTIMER Timer) // WDF timer object
{
    HardwareSimulator *pSimulator = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    pSimulator = GetHardwareSimulatorContextFromInstance(WdfTimerGetParentObject(Timer));
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Increment the sample index, roll over if the index reach the end of the array
        WdfWaitLockAcquire(pSimulator->m_Lock, NULL);
        pSimulator->m_Index++;
        pSimulator->m_Index = pSimulator->m_Index % ARRAYSIZE(SimulatorData);
        WdfWaitLockRelease(pSimulator->m_Lock);

        WdfTimerStart(pSimulator->m_Timer, WDF_REL_TIMEOUT_IN_MS(SIMULATOR_HARDWARE_INTERVAL_MS));
    }

    SENSOR_FunctionExit(Status);
}
Ejemplo n.º 2
0
NTSTATUS
TpmEvtDeviceD0Entry(
					IN  WDFDEVICE Device,
					IN  WDF_POWER_DEVICE_STATE PreviousState
    )
{
    PTPM_CONTEXT    TpmContext;
    NTSTATUS        status;

    UNREFERENCED_PARAMETER(PreviousState);

    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
                "TpmEvtDeviceD0Entry: Enter\n"));

    TpmContext = GetTpmContext(Device);

    TpmContext->AccessRegister = FALSE;

    TpmContinueSelfTest(TpmContext);

#if _NT_TARGET_VERSION >= 0x601
    TpmProvideEntropy(TpmContext);

    if(TpmContext->TimeOutSecond)
    {
        WdfTimerStart(TpmContext->timerHandle,
                      WDF_REL_TIMEOUT_IN_MS(TpmContext->TimeOutSecond));
    }
#endif

    TpmUpdateTpmState(TpmContext,StAvailable,IdPowerup);

    return STATUS_SUCCESS;
}
Ejemplo n.º 3
0
// Called by Sensor CLX to begin keeping history
NTSTATUS ActivityDevice::OnStartHistory(_In_ SENSOROBJECT sensorInstance)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
    if (nullptr == pDevice)
    {
        status = STATUS_INVALID_PARAMETER;
        TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
    }
    else if (0 == pDevice->m_HistorySizeInRecords)
    {
        status = STATUS_NOT_SUPPORTED;
        TraceError("ACT %!FUNC! Sensor does not support History");
    }
    else if (FALSE == pDevice->m_PoweredOn)
    {
        status = STATUS_DEVICE_NOT_READY;
        TraceError("ACT %!FUNC! Sensor is not powered on! %!STATUS!", status);
    }
    else
    {
        // Start keeping history
        pDevice->m_HistoryStarted = TRUE;
        WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs));
    }

    SENSOR_FunctionExit(status);
    return status;
}
Ejemplo n.º 4
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback reads current value, compare value to threshold,
// pushes it up to CLX framework, and schedule next wake up time.
VOID ActivityDevice::OnTimerExpire(_In_ WDFTIMER timer)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(timer));
    if (nullptr == pDevice)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
    }
    else
    {
        // Get data and push to clx
        WdfWaitLockAcquire(pDevice->m_Lock, NULL);
        status = pDevice->GetData();
        if (!NT_SUCCESS(status) && STATUS_DATA_NOT_ACCEPTED != status)
        {
            TraceError("ACT %!FUNC! GetAccData Failed %!STATUS!", status);
        }
        WdfWaitLockRelease(pDevice->m_Lock);

        // Schedule next wake up time
        if (Act_Default_MinDataInterval_Ms <= pDevice->m_Interval &&
            FALSE != pDevice->m_PoweredOn &&
            FALSE != pDevice->m_Started)
        {
            WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval));
        }
    }

    SENSOR_FunctionExit(status);
}
Ejemplo n.º 5
0
// Called by Sensor CLX to set sampling rate of the sensor.
NTSTATUS
CustomSensorDevice::OnSetDataInterval(
    _In_ SENSOROBJECT SensorInstance, // sensor device object
    _In_ ULONG DataRateMs             // sampling rate in milliseconds
    )
{
    PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance);
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (nullptr == pDevice || Cstm_Default_MinDataInterval_Ms > DataRateMs)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("CSTM %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT) SensorInstance, Status);
        goto Exit;
    }

    pDevice->m_Interval = DataRateMs;

    // reschedule sample to return as soon as possible if it's started
    if (FALSE != pDevice->m_Started)
    {
        pDevice->m_Started = FALSE;
        WdfTimerStop(pDevice->m_Timer, TRUE);

        pDevice->m_Started = TRUE;
        pDevice->m_FirstSample = TRUE;
        WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Cstm_Default_MinDataInterval_Ms));
    }

Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 6
0
/*++

Routine Description:

    Write to mail box in a serialize manner

Arguments:

    DeviceContextPtr - Pointer to device context

    Channel - Mailbox Channel

    Value - Value to be written

    Request - Optional WDF request object associated with this mailbox 
        transaction

Return Value:

    NTSTATUS

--*/
_Use_decl_annotations_
NTSTATUS RpiqMailboxWrite (
    DEVICE_CONTEXT* DeviceContextPtr,
    ULONG Channel,
    ULONG Value,
    WDFREQUEST Request
    )
{
    NTSTATUS status;
    ULONG count = 0, reg;
    LARGE_INTEGER timeOut = { 0 };

    PAGED_CODE();
    
    WdfWaitLockAcquire(DeviceContextPtr->WriteLock, NULL);

    timeOut.QuadPart = WDF_REL_TIMEOUT_IN_MS(1);

    reg = READ_REGISTER_NOFENCE_ULONG(&DeviceContextPtr->Mailbox->Status);

    // Poll until mailbox is available. It doesn't seem like
    // the mailbox is full often so polling is sufficient for now
    // rather than enable mailbox empty interrupt
    while (reg & MAILBOX_STATUS_FULL) {
        if (count > MAX_POLL) {
            RPIQ_LOG_ERROR(
                "Exit Fail Status 0x%08x", 
                DeviceContextPtr->Mailbox->Status);
            status = STATUS_IO_TIMEOUT;
            goto End;
        }

        KeDelayExecutionThread(KernelMode, FALSE, &timeOut);
        reg = READ_REGISTER_NOFENCE_ULONG(&DeviceContextPtr->Mailbox->Status);
        ++count;
    }

    if (Request) {
        status = WdfRequestForwardToIoQueue(
            Request,
            DeviceContextPtr->ChannelQueue[Channel]);
        if (!NT_SUCCESS(status)) {
            RPIQ_LOG_ERROR(
                "WdfRequestForwardToIoQueue failed ( %!STATUS!)",
                status);
            goto End;
        }
    }

    WRITE_REGISTER_NOFENCE_ULONG(
        &DeviceContextPtr->Mailbox->Write, 
        (Value & ~MAILBOX_CHANNEL_MASK) | Channel);

    status = STATUS_SUCCESS;

End:
    WdfWaitLockRelease(DeviceContextPtr->WriteLock);

    return status;
}
Ejemplo n.º 7
0
VOID
PLxHardwareReset(
    IN PDEVICE_EXTENSION DevExt
    )
/*++
Routine Description:

    Called by D0Exit when the device is being disabled or when the system is shutdown to
    put the device in a known initial state.

Arguments:

    DevExt     Pointer to Device Extension

Return Value:

--*/
{
    LARGE_INTEGER delay;

    union {
        EEPROM_CSR  bits;
        ULONG       ulong;
    } eeCSR;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> PLxIssueFullReset");

    //
    // Drive the 9656 into soft reset.
    //
    eeCSR.ulong =
        READ_REGISTER_ULONG( (PULONG) &DevExt->Regs->EEPROM_Ctrl_Stat );

    eeCSR.bits.SoftwareReset = TRUE;

    WRITE_REGISTER_ULONG( (PULONG) &DevExt->Regs->EEPROM_Ctrl_Stat,
                          eeCSR.ulong );

    //
    // Wait 100 msec.
    //
    delay.QuadPart =  WDF_REL_TIMEOUT_IN_MS(100);

    KeDelayExecutionThread( KernelMode, TRUE, &delay );

    //
    // Finally pull the 9656 out of reset.
    //
    eeCSR.bits.SoftwareReset = FALSE;

    WRITE_REGISTER_ULONG( (PULONG) &DevExt->Regs->EEPROM_Ctrl_Stat,
                          eeCSR.ulong );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- PLxIssueFullReset");
}
Ejemplo n.º 8
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback stores activity data in history buffer,
// and schedules next wake up time.
VOID ActivityDevice::OnHistoryTimerExpire(_In_ WDFTIMER historyTimer)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(historyTimer));
    if (nullptr == pDevice)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
    }
    else
    {
        ActivitySample data = {};
        if (NULL != pDevice->m_SimulatorInstance)
        {
            PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
            if (nullptr != pSimulator)
            {
                status = pSimulator->GetSample(&data);
            }
            else
            {
                status = STATUS_INVALID_PARAMETER;
            }
        }
        GetSystemTimePreciseAsFileTime(&(data.Timestamp));

        if (NT_SUCCESS(status))
        {
            // Add data to the buffer
            WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
            status = pDevice->AddDataElementToHistoryBuffer(&data);
            if (!NT_SUCCESS(status))
            {
                TraceError("ACT %!FUNC! AddDataElementToHistoryBuffer Failed %!STATUS!", status);
            }
            WdfWaitLockRelease(pDevice->m_HistoryLock);
        }

        // Schedule next wake up time
        if (FALSE != pDevice->m_HistoryStarted)
        {
            WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs));
        }
    }

    SENSOR_FunctionExit(status);
}
Ejemplo n.º 9
0
// Called by Sensor CLX to begin continuously sampling the sensor.
NTSTATUS
PedometerDevice::OnStart(
    _In_ SENSOROBJECT SensorInstance // Sensor device object
    )
{
    PHardwareSimulator pSimulator = nullptr;
    PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (nullptr == pDevice)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
        goto Exit;
    }

    // Get the simulator context
    pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Start the simulator
        pSimulator->Start();

        pDevice->m_FirstSample = TRUE;

        // Start polling

        pDevice->m_Started = TRUE;

        InitPropVariantFromUInt32(SensorState_Active,
            &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));

        // Start the sample polling timer.
        //
        // Note: The polling timer is configured to allow for the first sample to be reported immediately.
        // Some hardware may want to delay the first sample report a little to account for hardware start time.
        WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Pedometer_Default_MinDataInterval_Ms));
    }
Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
// This routine starts the simulator
// Returns an NTSTATUS code
NTSTATUS HardwareSimulator::Start()
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (SimulatorState_Initialized == m_State)
    {
        WdfTimerStart(m_Timer, WDF_REL_TIMEOUT_IN_MS(HardwareSimulator_HardwareInterval));
        m_State = SimulatorState_Started;
    }

    SENSOR_FunctionExit(status);

    return status;
}
Ejemplo n.º 11
0
NTSTATUS
EchoEvtDeviceSelfManagedIoStart(
    IN  WDFDEVICE Device
    )
/*++

Routine Description:

    This event is called by the Framework when the device is started
    or restarted after a suspend operation.

    This function is not marked pageable because this function is in the
    device power up path. When a function is marked pagable and the code
    section is paged out, it will generate a page fault which could impact
    the fast resume behavior because the client driver will have to wait
    until the system drivers can service this page fault.

Arguments:

    Device - Handle to a framework device object.

Return Value:

    NTSTATUS - Failures will result in the device stack being torn down.

--*/
{
    PQUEUE_CONTEXT queueContext = QueueGetContext(WdfDeviceGetDefaultQueue(Device));
    LARGE_INTEGER DueTime;

    KdPrint(("--> EchoEvtDeviceSelfManagedIoInit\n"));

    //
    // Restart the queue and the periodic timer. We stopped them before going
    // into low power state.
    //
    WdfIoQueueStart(WdfDeviceGetDefaultQueue(Device));

    DueTime.QuadPart = WDF_REL_TIMEOUT_IN_MS(100);

    WdfTimerStart(queueContext->Timer,  DueTime.QuadPart);

    KdPrint(( "<-- EchoEvtDeviceSelfManagedIoInit\n"));

    return STATUS_SUCCESS;
}
Ejemplo n.º 12
0
// Called by Sensor CLX to begin continously sampling the sensor.
NTSTATUS ActivityDevice::OnStart(_In_ SENSOROBJECT sensorInstance)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
    if (nullptr == pDevice)
    {
        status = STATUS_INVALID_PARAMETER;
        TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
    }
    else
    {
        if (FALSE == pDevice->m_PoweredOn)
        {
            status = STATUS_DEVICE_NOT_READY;
            TraceError("ACT %!FUNC! Sensor is not powered on! %!STATUS!", status);
        }
        else
        {
            // Start simulation
            if (NULL != pDevice->m_SimulatorInstance)
            {
                PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
                if (nullptr != pSimulator)
                {
                    pSimulator->Start();
                }
            }

            // Start sensing
            pDevice->m_FirstSample = TRUE;
            pDevice->m_Started = TRUE;
            InitPropVariantFromUInt32(SensorState_Active, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
            WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Act_Default_MinDataInterval_Ms));
        }
    }

    SENSOR_FunctionExit(status);
    return status;
}
Ejemplo n.º 13
0
NTSTATUS BOOTTRACKPAD(
	_In_  PDEVICE_CONTEXT  pDevice
	)
{
	NTSTATUS status = 0;

	static char bl_exit[] = {
		0x00, 0xff, 0xa5, 0x00, 0x01,
		0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };

	static char bl_deactivate[] = {
		0x00, 0xff, 0x3b, 0x00, 0x01,
		0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };

	cyapa_boot_regs boot;

	FuncEntry(TRACE_FLAG_WDFLOADING);

	SpbReadDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, &boot, sizeof(boot));

	if ((boot.stat & CYAPA_STAT_RUNNING) == 0) {
		if (boot.error & CYAPA_ERROR_BOOTLOADER)
			SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_deactivate, sizeof(bl_deactivate));
		else
			SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_exit, sizeof(bl_exit));
	}

	WDF_TIMER_CONFIG              timerConfig;
	WDFTIMER                      hTimer;
	WDF_OBJECT_ATTRIBUTES         attributes;

	WDF_TIMER_CONFIG_INIT(&timerConfig, CyapaBootTimer);

	WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
	attributes.ParentObject = pDevice->FxDevice;
	status = WdfTimerCreate(&timerConfig, &attributes, &hTimer);

	WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(75));

	FuncExit(TRACE_FLAG_WDFLOADING);
	return status;
}
Ejemplo n.º 14
0
NTSTATUS
OnD0Entry(
    _In_  WDFDEVICE               FxDevice,
    _In_  WDF_POWER_DEVICE_STATE  FxPreviousState
    )
/*++
 
  Routine Description:

    This routine allocates objects needed by the driver.

  Arguments:

    FxDevice - a handle to the framework device object
    FxPreviousState - previous power state

  Return Value:

    Status

--*/
{
    FuncEntry(TRACE_FLAG_WDFLOADING);
    
    UNREFERENCED_PARAMETER(FxPreviousState);

    PDEVICE_CONTEXT pDevice = GetDeviceContext(FxDevice);
    NTSTATUS status = STATUS_SUCCESS;

	WdfTimerStart(pDevice->Timer, WDF_REL_TIMEOUT_IN_MS(10));

	BOOTTRACKPAD(pDevice);

	pDevice->RegsSet = false;
	pDevice->ConnectInterrupt = true;

    FuncExit(TRACE_FLAG_WDFLOADING);

    return status;
}
Ejemplo n.º 15
0
VOID TpmEvtEntropyTimer(IN WDFTIMER  Timer)
{
#if _NT_TARGET_VERSION >= 0x601

    ULONG			Interval;
    PTPM_CONTEXT    TpmContext;

	PAGED_CODE();

	TpmContext = GetTimerContext(Timer)->TpmContext;

    KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL,
            "TpmEvtEntropyTimer().\n"));

    if(TpmContext->bUseTimeOut)
    {
        TpmContext->PendingEntropy = TRUE;
        if(NT_SUCCESS(TpmUpdateTpmState(TpmContext,StBusy,IdEntropy)))
        {
            TpmProvideEntropy(TpmContext);
            TpmUpdateTpmState(TpmContext,StAvailable,IdEntropy);
        }
    }
    else
    {
		if(NT_SUCCESS(TpmGetEntropyInterval(&Interval)))
		{
            TpmContext->TimeOutSecond = 60000 * Interval;
            TpmContext->bUseTimeOut = TRUE;
       }
    }

    if(TpmContext->TimeOutSecond)
    {
        WdfTimerStart(TpmContext->timerHandle,
                      WDF_REL_TIMEOUT_IN_MS(TpmContext->TimeOutSecond));
    }
#endif
}
Ejemplo n.º 16
0
/*++
Routine Description:

This routine sets a property on a pipe.

Arguments:

pDeviceContext - Device context handle
pControlTransfer - The control transfer property struct

Return Value:

NT status value
--*/
NTSTATUS ControlTransfer(IN PDEVICE_CONTEXT pDeviceContext, IN PSUSBDRV_CONTROL_TRANSFER* pControlTransfer, IN OUT PUCHAR pControlBuffer, IN size_t nControlBufferSize, OUT ULONG* pLength)
{
	NTSTATUS						status = STATUS_SUCCESS;
	unsigned int					nTimeout = PSUSBDRV_DEFAULT_CONTROL_TIMEOUT;
	WDF_REQUEST_SEND_OPTIONS		sendOptions;
	WDF_USB_CONTROL_SETUP_PACKET	controlSetupPacket;
	WDF_MEMORY_DESCRIPTOR			memDesc;

	PAGED_CODE();

	RtlZeroMemory(&controlSetupPacket, sizeof(WDF_USB_CONTROL_SETUP_PACKET));

	controlSetupPacket.Packet.bm.Request.Dir = pControlTransfer->cDirection;
	controlSetupPacket.Packet.bm.Request.Type = pControlTransfer->cRequestType;
	controlSetupPacket.Packet.bm.Request.Recipient = BmRequestToDevice;
	controlSetupPacket.Packet.bRequest = pControlTransfer->cRequest;
	controlSetupPacket.Packet.wValue.Value = pControlTransfer->nValue;
	controlSetupPacket.Packet.wIndex.Value = pControlTransfer->nIndex;

	PSDrv_DbgPrint(3, ("ControlTransfer: Dir:%d Type:%d Request:%d Value:%d Index:%d.\n", pControlTransfer->cDirection, pControlTransfer->cRequestType,  pControlTransfer->cRequest, pControlTransfer->nValue, pControlTransfer->nIndex));

	if (pControlTransfer->nTimeout != 0)
	{
		if (pControlTransfer->nTimeout > PSUSBDRV_DEFAULT_CONTROL_TIMEOUT)
		{
			PSDrv_DbgPrint(3, ("ControlTransfer: Timeout was truncated from %d to %d!\n", pControlTransfer->nTimeout, PSUSBDRV_DEFAULT_CONTROL_TIMEOUT));

			nTimeout = PSUSBDRV_DEFAULT_CONTROL_TIMEOUT;
		}
		else
		{
			nTimeout = pControlTransfer->nTimeout;
		}
	}

	WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT);
	WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(nTimeout));	

	PSDrv_DbgPrint(3, ("ControlTransfer: Timeout is set to: %d.\n", nTimeout));

	PSDrv_DbgPrint(3, ("ControlTransfer: Performing the control transfer...\n"));

	if (pControlBuffer != NULL)
	{
		PSDrv_DbgPrint(3, ("ControlTransfer: Buffer:%x Length:%d\n", pControlBuffer, nControlBufferSize));

		if (nControlBufferSize == 0)
		{
			PSDrv_DbgPrint(3, ("ControlTransfer: pControlBuffer is not NULL but nControlBufferSize is 0!\n"));

			return (STATUS_INVALID_PARAMETER);
		}

		WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memDesc, pControlBuffer, (ULONG)nControlBufferSize);

		status = WdfUsbTargetDeviceSendControlTransferSynchronously(pDeviceContext->WdfUsbTargetDevice, WDF_NO_HANDLE, &sendOptions, &controlSetupPacket, &memDesc, pLength);
	}
	else
	{
		status = WdfUsbTargetDeviceSendControlTransferSynchronously(pDeviceContext->WdfUsbTargetDevice, WDF_NO_HANDLE, &sendOptions, &controlSetupPacket, NULL, pLength);
	}

	PSDrv_DbgPrint(3, ("ControlTransfer: Finished! Status=%x BytesTransferred=%d\n", status, *pLength));

	return status;
}
Ejemplo n.º 17
0
Archivo: usb.c Proyecto: uri247/wdk80
VOID
HidFx2EvtUsbInterruptPipeReadComplete(
    WDFUSBPIPE  Pipe,
    WDFMEMORY   Buffer,
    size_t      NumBytesTransferred,
    WDFCONTEXT  Context
    )
/*++

Routine Description:

    This the completion routine of the continuous reader. This can
    called concurrently on multiprocessor system if there are
    more than one readers configured. So make sure to protect
    access to global resources.

Arguments:

    Pipe - Handle to WDF USB pipe object

    Buffer - This buffer is freed when this call returns.
             If the driver wants to delay processing of the buffer, it
             can take an additional referrence.

    NumBytesTransferred - number of bytes of data that are in the read buffer.

    Context - Provided in the WDF_USB_CONTINUOUS_READER_CONFIG_INIT macro

Return Value:

    NT status value

--*/
{
    PDEVICE_EXTENSION  devContext = Context;
    UCHAR              toggledSwitch = 0;
    PUCHAR             switchState = NULL;
    UCHAR              currentSwitchState = 0;
    UCHAR              previousSwitchState = 0;

    UNREFERENCED_PARAMETER(NumBytesTransferred);
    UNREFERENCED_PARAMETER(Pipe);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
        "HidFx2EvtUsbInterruptPipeReadComplete Enter\n");

    //
    // Interrupt endpoints sends switch state when first started
    // or when resuming from suspend. We need to ignore that data since
    // user did not change the switch state.
    //
    if (devContext->IsPowerUpSwitchState) {
        devContext->IsPowerUpSwitchState = FALSE;

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
            "Dropping interrupt message since received during powerup/resume\n");
        return;
    }


    //
    // Make sure that there is data in the read packet.  Depending on the device
    // specification, it is possible for it to return a 0 length read in
    // certain conditions.
    //

    if (NumBytesTransferred == 0) {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_INIT,
                    "HidFx2EvtUsbInterruptPipeReadComplete Zero length read "
                    "occured on the Interrupt Pipe's Continuous Reader\n"
                    );
        return;
    }
    
    switchState = WdfMemoryGetBuffer(Buffer, NULL);

    currentSwitchState = *switchState;
    previousSwitchState = devContext->CurrentSwitchState;

    //
    // we want to know which switch got toggled from 0 to 1
    // Since the device returns the state of all the swicthes and not just the
    // one that got toggled, we need to store previous state and xor
    // it with current state to know whcih one swicth got toggled.
    // Further, the toggle is considered "on" only when it changes from 0 to 1
    // (and not when it changes from 1 to 0).
    //
    toggledSwitch = (previousSwitchState ^ currentSwitchState) & currentSwitchState;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                "HidFx2EvtUsbInterruptPipeReadComplete SwitchState %x, "
                "prevSwitch:0x%x, x0R:0x%x\n",
                currentSwitchState,
                previousSwitchState,
                toggledSwitch
                );

    //
    // Store switch state in device context
    //
    devContext->CurrentSwitchState = *switchState;
    //if (toggledSwitch != 0) {
        devContext->LatestToggledSwitch = toggledSwitch;
    //}

    //
    // Complete pending Read requests if there is at least one switch toggled
    // to on position.
    //
    if (toggledSwitch != 0) {
        BOOLEAN inTimerQueue;

        //
        // Debounce the switchpack. A simple logic is used for debouncing.
        // A timer is started for 10 ms everytime there is a switch toggled on.
        // If within 10 ms same or another switch gets toggled, the timer gets
        // reset for another 10 ms. The HID read request is completed in timer
        // function if there is still a switch in toggled-on state. Note that
        // debouncing happens at the whole switch pack level (not individual
        // switches) which means if two different switches are toggled-on within
        // 10 ms only one of them (later one in this case) will get accepted and
        // sent to hidclass driver
        //
        inTimerQueue = WdfTimerStart(
            devContext->DebounceTimer,
            WDF_REL_TIMEOUT_IN_MS(SWICTHPACK_DEBOUNCE_TIME_IN_MS)
            );

        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
            "Debounce Timer started with timeout of %d ms"
            " (TimerReturnValue:%d)\n",
            SWICTHPACK_DEBOUNCE_TIME_IN_MS, inTimerQueue);
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
        "HidFx2EvtUsbInterruptPipeReadComplete Exit\n");
}
Ejemplo n.º 18
0
NTSTATUS
Toastmon_OpenDevice(
    WDFDEVICE Device,
    PUNICODE_STRING SymbolicLink,
    WDFIOTARGET *Target
    )
/*++

Routine Description:

    Open the I/O target and preallocate any resources required
    to communicate with the target device.

Arguments:

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS                    status = STATUS_SUCCESS;
    PTARGET_DEVICE_INFO         targetDeviceInfo = NULL;
    WDF_IO_TARGET_OPEN_PARAMS   openParams;
    WDFIOTARGET                 ioTarget;
    WDF_OBJECT_ATTRIBUTES       attributes;
    PDEVICE_EXTENSION           deviceExtension = GetDeviceExtension(Device);
    WDF_TIMER_CONFIG            wdfTimerConfig;
    

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TARGET_DEVICE_INFO);

    status = WdfIoTargetCreate(deviceExtension->WdfDevice,
                            &attributes,
                            &ioTarget);
    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfIoTargetCreate failed 0x%x\n", status));
        return status;
    }

    targetDeviceInfo = GetTargetDeviceInfo(ioTarget);
    targetDeviceInfo->DeviceExtension = deviceExtension;

    //
    // Warning: It's not recommended to open the targetdevice
    // from a pnp notification callback routine, because if
    // the target device initiates any kind of PnP action as
    // a result of this open, the PnP manager could deadlock.
    // You should queue a workitem to do that.
    // For example, SWENUM devices in conjunction with KS
    // initiate an enumeration of a device when you do the
    // open on the device interface.
    // We can open the target device here because we know the
    // toaster function driver doesn't trigger any pnp action.
    //

    WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
        &openParams,
        SymbolicLink,
        STANDARD_RIGHTS_ALL);

    openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ;
    //
    // Framework provides default action for all of these if you don't register
    // these callbacks -it will close the handle to the target when the device is
    // being query-removed and reopen it if the query-remove fails.
    // In this sample, we use a periodic timers to post requests to the target.
    // So we need to register these callbacks so that we can start and stop
    // the timer when the state of the target device changes. Since we are
    // registering these callbacks, we are now responsbile for closing and
    // reopening the target.
    //
    openParams.EvtIoTargetQueryRemove = ToastMon_EvtIoTargetQueryRemove;
    openParams.EvtIoTargetRemoveCanceled = ToastMon_EvtIoTargetRemoveCanceled;
    openParams.EvtIoTargetRemoveComplete = ToastMon_EvtIoTargetRemoveComplete;


    status = WdfIoTargetOpen(ioTarget, &openParams);

    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfIoTargetOpen failed with status 0x%x\n", status));
        WdfObjectDelete(ioTarget);
        return status;
    }
   
    KdPrint(("Target Device 0x%x, PDO 0x%x, Fileobject 0x%x, Filehandle 0x%x\n",
                        WdfIoTargetWdmGetTargetDeviceObject(ioTarget),
                        WdfIoTargetWdmGetTargetPhysicalDevice(ioTarget),
                        WdfIoTargetWdmGetTargetFileObject(ioTarget),
                        WdfIoTargetWdmGetTargetFileHandle(ioTarget)));

    //
    // Create two requests - one for read and one for write.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = ioTarget;

    status = WdfRequestCreate(&attributes,
                              ioTarget,
                              &targetDeviceInfo->ReadRequest);

    if (!NT_SUCCESS(status)) {
        WdfObjectDelete(ioTarget);
        return status;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = ioTarget;

    status = WdfRequestCreate(&attributes,
                            ioTarget,
                            &targetDeviceInfo->WriteRequest);

    if (!NT_SUCCESS(status)) {
        WdfObjectDelete(ioTarget);
        return status;
    }

    //
    // Create a passive timer to post requests to the I/O target.
    //
    WDF_TIMER_CONFIG_INIT(&wdfTimerConfig,
                          Toastmon_EvtTimerPostRequests);
     
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, TIMER_CONTEXT);

    //
    // Make IoTarget as parent of the timer to prevent the ioTarget
    // from deleted until the dpc has runto completion.
    //
    attributes.ParentObject = ioTarget;

    //
    // By specifying WdfExecutionLevelPassive the framework will invoke
    // the timer callback Toastmon_EvtTimerPostRequests at PASSIVE_LEVEL.
    //
    attributes.ExecutionLevel = WdfExecutionLevelPassive;

    //
    // Setting the AutomaticSerialization to FALSE prevents
    // WdfTimerCreate to fail if the parent device object's 
    // execution level is set to WdfExecutionLevelPassive.
    //
    wdfTimerConfig.AutomaticSerialization = FALSE;
    
    status = WdfTimerCreate(&wdfTimerConfig,
                       &attributes,
                       &targetDeviceInfo->TimerForPostingRequests
                       );

    if(!NT_SUCCESS(status)) {
        KdPrint(("WdfTimerCreate failed 0x%x\n", status));
        WdfObjectDelete(ioTarget);
        return status;
    }

    GetTimerContext(targetDeviceInfo->TimerForPostingRequests)->IoTarget = ioTarget;

    //
    // Start the passive timer. The first timer will be queued after 1ms  interval and
    // after that it will be requeued in the timer callback function. 
    // The value of 1 ms (lowest timer resoltion allowed on NT) is chosen here so 
    // that timer would fire right away.
    //
    WdfTimerStart(targetDeviceInfo->TimerForPostingRequests,
                                        WDF_REL_TIMEOUT_IN_MS(1));

    *Target = ioTarget;

    return status;

}
Ejemplo n.º 19
0
/*++
Routine Description:

This callback is invoked when the framework received  WdfRequestTypeRead or
WdfRequestTypeWrite request. This read/write is performed in stages of
MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the
request is circulated again, until the requested length of transfer is
performed.

Arguments:

Queue - Handle to the framework queue object that is associated
with the I/O request.

Request - Handle to a framework request object. This one represents
the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

Length - Length of the input/output buffer.

Return Value:

VOID
--*/
VOID ReadWriteBulkEndPoints(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType)
{
    PMDL						newMdl = NULL;
	PMDL						requestMdl = NULL;
    PURB						urb = NULL;
    WDFMEMORY					urbMemory;
    ULONG						totalLength = Length;
    ULONG						stageLength = 0;
    ULONG						urbFlags = 0;
    NTSTATUS					status;
    ULONG_PTR					virtualAddress = 0;
    PREQUEST_CONTEXT			rwContext = NULL;
    PFILE_CONTEXT				fileContext = NULL;
    WDFUSBPIPE					pipe;
    WDF_USB_PIPE_INFORMATION	pipeInfo;
    WDF_OBJECT_ATTRIBUTES		objectAttribs;
    USBD_PIPE_HANDLE			usbdPipeHandle;
    PDEVICE_CONTEXT				deviceContext;
	WDF_REQUEST_SEND_OPTIONS	sendOptions;

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - begins\n"));

    // First validate input parameters.
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize)
	{
        PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) && (RequestType != WdfRequestTypeWrite))
	{
        PSDrv_DbgPrint(1, ("RequestType has to be either Read or Write! (RequestType = %d)\n", RequestType));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    // Get the pipe associate with this request.
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;
    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

    if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType))
	{
        PSDrv_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt! (PipeType = %d)\n", pipeInfo.PipeType));
        status = STATUS_INVALID_DEVICE_REQUEST;
        goto Exit;
    }

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead)
	{
        status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
            PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed! (Status = %x)\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        rwContext->Read = TRUE;
        PSDrv_DbgPrint(3, ("This is a read operation...\n"));
    }
	else
	{
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
			PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed! (Status = %x)\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        rwContext->Read = FALSE;
        PSDrv_DbgPrint(3, ("This is a write operation...\n"));
    }


    urbFlags |= USBD_SHORT_TRANSFER_OK;

    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

    // The transfer request is for totalLength. We can perform a max of MAX_TRANSFER_SIZE in each stage.
    if (totalLength > MAX_TRANSFER_SIZE)
	{
        stageLength = MAX_TRANSFER_SIZE;
    }
    else
	{
        stageLength = totalLength;
    }

    newMdl = IoAllocateMdl((PVOID)virtualAddress, totalLength, FALSE, FALSE, NULL);
    if (newMdl == NULL)
	{
        PSDrv_DbgPrint(1, ("IoAllocateMdl failed! (newMdl is NULL)\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    // Map the portion of user-buffer described by an mdl to another mdl
    IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength);

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;

    status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*)&urb);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfMemoryCreate for urbMemory failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

    UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL);

    status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL);

    // Set REQUEST_CONTEXT parameters.
    rwContext->UrbMemory       = urbMemory;
    rwContext->Mdl             = newMdl;
    rwContext->Length          = totalLength - stageLength;
    rwContext->Numxfer         = 0;
    rwContext->VirtualAddress  = virtualAddress + stageLength;

	// Set the timeout
	if (fileContext->nTimeOut != 0)
	{
		WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT);
		WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(fileContext->nTimeOut));

		PSDrv_DbgPrint(3, ("Pipe timeout is set to: %d\n", fileContext->nTimeOut));

		if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), &sendOptions))
		{
			status = WdfRequestGetStatus(Request);
			ASSERT(!NT_SUCCESS(status));
		}
	}
	else
	{
		if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS))
		{
			status = WdfRequestGetStatus(Request);
			ASSERT(!NT_SUCCESS(status));
		}
	}

Exit:
    if (!NT_SUCCESS(status))
	{
        WdfRequestCompleteWithInformation(Request, status, 0);

        if (newMdl != NULL)
		{
            IoFreeMdl(newMdl);
        }
    }

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - ends\n"));

    return;
}
Ejemplo n.º 20
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback reads current value, compare value to threshold,
// pushes it up to CLX framework, and schedule next wake up time.
VOID
PedometerDevice::OnTimerExpire(
    _In_ WDFTIMER Timer // WDF timer object
    )
{
    PPedometerDevice pDevice = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    pDevice = GetPedometerContextFromSensorInstance(WdfTimerGetParentObject(Timer));
    if (nullptr == pDevice)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetPedometerContextFromSensorInstance failed %!STATUS!", Status);
        goto Exit;
    }

    // Get data and push to clx
    WdfWaitLockAcquire(pDevice->m_Lock, NULL);
    Status = pDevice->GetData();
    if (!NT_SUCCESS(Status) && Status != STATUS_DATA_NOT_ACCEPTED)
    {
        TraceError("PED %!FUNC! GetData Failed %!STATUS!", Status);
    }
    WdfWaitLockRelease(pDevice->m_Lock);

    // Schedule next wake up time
    if (FALSE != pDevice->m_PoweredOn &&
        FALSE != pDevice->m_Started)
    {
        LONGLONG WaitTimeHundredNanoseconds = 0;  // in unit of 100ns

        if (0 == pDevice->m_StartTime)
        {
            // in case we fail to get sensor start time, use static wait time
            WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
        }
        else
        {
            ULONG CurrentTimeMs = 0;

            // dynamically calculate wait time to avoid jitter
            Status = GetPerformanceTime (&CurrentTimeMs);
            if (!NT_SUCCESS(Status))
            {
                TraceError("PED %!FUNC! GetPerformanceTime %!STATUS!", Status);
                WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
            }
            else
            {
                pDevice->m_SampleCount++;
                if (CurrentTimeMs > (pDevice->m_StartTime + (pDevice->m_Interval * (pDevice->m_SampleCount + 1))))
                {
                    // If we skipped two or more beats, reschedule the timer with a zero due time to catch up on missing samples
                    WaitTimeHundredNanoseconds = 0;
                }
                else
                {
                    WaitTimeHundredNanoseconds = (pDevice->m_StartTime +
                        (pDevice->m_Interval * (pDevice->m_SampleCount + 1))) - CurrentTimeMs;
                }
                WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(WaitTimeHundredNanoseconds);
            }
        }
        WdfTimerStart(pDevice->m_Timer, WaitTimeHundredNanoseconds);
    }

Exit:

    SENSOR_FunctionExit(Status);
}
Ejemplo n.º 21
0
VOID
EvtIoDeviceControl(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     OutputBufferLength,
    IN size_t     InputBufferLength,
    IN ULONG      IoControlCode
    )
{
    WDFDEVICE                           device;
    PDEVICE_CONTEXT                     pDevContext;
    size_t                              bytesTransferred = 0;
    NTSTATUS                            status;
    WDF_USB_CONTROL_SETUP_PACKET        controlSetupPacket;
    WDF_MEMORY_DESCRIPTOR               memDesc;
    WDFMEMORY                           memory;
    WDF_REQUEST_SEND_OPTIONS            sendOptions;

    UNREFERENCED_PARAMETER(InputBufferLength);
    UNREFERENCED_PARAMETER(OutputBufferLength);

    device = WdfIoQueueGetDevice(Queue);
    pDevContext = GetDeviceContext(device);

    switch(IoControlCode) {

    case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY:

        if(InputBufferLength < sizeof(UCHAR)) {
            status = STATUS_BUFFER_OVERFLOW;
            bytesTransferred = sizeof(UCHAR);
            break;
        }

        status = WdfRequestRetrieveInputMemory(Request, &memory);
        if (!NT_SUCCESS(status)) {
            KdPrint(("WdfRequestRetrieveMemory failed %!STATUS!", status));
            break;
        }

        WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
                                        BmRequestHostToDevice,
                                        BmRequestToDevice,
                                        USBFX2LK_SET_BARGRAPH_DISPLAY, // Request
                                        0, // Value
                                        0); // Index

        WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDesc, memory, NULL);

       //
       // Send the I/O with a timeout to avoid hanging the calling 
       // thread indefinitely.
       //
        WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions,
                                  WDF_REQUEST_SEND_OPTION_TIMEOUT);

        WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions,
                                         WDF_REL_TIMEOUT_IN_MS(100));

        status = WdfUsbTargetDeviceSendControlTransferSynchronously(
                                        pDevContext->UsbDevice,
                                        NULL, // Optional WDFREQUEST
                                        &sendOptions, // PWDF_REQUEST_SEND_OPTIONS
                                        &controlSetupPacket,
                                        &memDesc,
                                        (PULONG)&bytesTransferred);
        if (!NT_SUCCESS(status)) {
            KdPrint(("SendControlTransfer failed %!STATUS!", status));
            break;
        }
        break;

    default:
        status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    WdfRequestCompleteWithInformation(Request, status, bytesTransferred);

    return;
}
Ejemplo n.º 22
0
NTSTATUS
Acpi_EvaluateUcsiDsm (
    _In_ PACPI_CONTEXT AcpiCtx,
    _In_ ULONG FunctionIndex,
    _Outptr_opt_ PACPI_EVAL_OUTPUT_BUFFER* Output
    )
/*++

    N.B. Caller is expected to free the Output buffer.

--*/
{
    NTSTATUS status;
    WDFDEVICE device;
    WDFMEMORY inputMemory;
    WDF_MEMORY_DESCRIPTOR inputMemDesc;
    PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer;
    size_t inputBufferSize;
    size_t inputArgumentBufferSize;
    PACPI_METHOD_ARGUMENT argument;
    WDF_MEMORY_DESCRIPTOR outputMemDesc;
    PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    size_t outputBufferSize;
    size_t outputArgumentBufferSize;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_REQUEST_SEND_OPTIONS sendOptions;

    PAGED_CODE();

    TRACE_FUNC_ENTRY(TRACE_FLAG_ACPI);

    device = Context_GetWdfDevice(AcpiCtx);
    inputMemory = WDF_NO_HANDLE;
    outputBuffer = nullptr;

    inputArgumentBufferSize =
        ACPI_METHOD_ARGUMENT_LENGTH(sizeof(GUID)) +
        ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) +
        ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) +
        ACPI_METHOD_ARGUMENT_LENGTH(0);

    inputBufferSize =
        FIELD_OFFSET(ACPI_EVAL_INPUT_BUFFER_COMPLEX, Argument) +
        inputArgumentBufferSize;

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = device;

    status = WdfMemoryCreate(&attributes,
                             NonPagedPoolNx,
                             0,
                             inputBufferSize,
                             &inputMemory,
                             (PVOID*) &inputBuffer);

    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate failed for %Iu bytes - %!STATUS!", device, inputBufferSize, status);
        goto Exit;
    }

    RtlZeroMemory(inputBuffer, inputBufferSize);

    inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
    inputBuffer->Size = (ULONG) inputArgumentBufferSize;
    inputBuffer->ArgumentCount = 4;
    inputBuffer->MethodNameAsUlong = (ULONG) 'MSD_';

    argument = &(inputBuffer->Argument[0]);
    ACPI_METHOD_SET_ARGUMENT_BUFFER(argument,
                                    &GUID_UCSI_DSM,
                                    sizeof(GUID_UCSI_DSM));

    argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
    ACPI_METHOD_SET_ARGUMENT_INTEGER(argument, UCSI_DSM_REVISION);

    argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
    ACPI_METHOD_SET_ARGUMENT_INTEGER(argument, FunctionIndex);

    argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
    argument->Type = ACPI_METHOD_ARGUMENT_PACKAGE_EX;
    argument->DataLength = 0;

    outputArgumentBufferSize = ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG));
    outputBufferSize =
        FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
        outputArgumentBufferSize;

    outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER) ExAllocatePoolWithTag(NonPagedPoolNx,
                                                                    outputBufferSize,
                                                                    TAG_UCSI);

    if (outputBuffer == nullptr)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] ExAllocatePoolWithTag failed for %Iu bytes", device, outputBufferSize);
        goto Exit;
    }

    RtlZeroMemory(outputBuffer, outputBufferSize);

    WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemDesc, inputMemory, NULL);
    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputMemDesc, outputBuffer, (ULONG) outputBufferSize);

    WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions,
                                         WDF_REL_TIMEOUT_IN_MS(UCSI_DSM_EXECUTION_TIMEOUT_IN_MS));

    status = WdfIoTargetSendInternalIoctlSynchronously(
                 WdfDeviceGetIoTarget(device),
                 NULL,
                 IOCTL_ACPI_EVAL_METHOD,
                 &inputMemDesc,
                 &outputMemDesc,
                 &sendOptions,
                 NULL);

    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] IOCTL_ACPI_EVAL_METHOD for _DSM failed - %!STATUS!", device, status);
        goto Exit;
    }

    if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE)
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] ACPI_EVAL_OUTPUT_BUFFER signature is incorrect", device);
        status = STATUS_ACPI_INVALID_DATA;
        goto Exit;
    }

Exit:

    if (inputMemory != WDF_NO_HANDLE)
    {
        WdfObjectDelete(inputMemory);
    }

    if (!NT_SUCCESS(status) || (Output == nullptr))
    {
        if (outputBuffer)
        {
            ExFreePoolWithTag(outputBuffer, TAG_UCSI);
        }
    }
    else
    {
        *Output = outputBuffer;
    }

    TRACE_FUNC_EXIT(TRACE_FLAG_ACPI);

    return status;
}
Ejemplo n.º 23
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback reads current value,
// pushes it up to CLX framework, and schedule next wake up time.
VOID
CustomSensorDevice::OnTimerExpire(
    _In_ WDFTIMER Timer // WDF timer object
    )
{
    PCustomSensorDevice pDevice = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    pDevice = GetCustomSensorContextFromSensorInstance(WdfTimerGetParentObject(Timer));
    if (nullptr == pDevice)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("CSTM %!FUNC! GetCustomSensorContextFromSensorInstance failed %!STATUS!", Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Get data and push to clx
        WdfWaitLockAcquire(pDevice->m_Lock, NULL);
        Status = pDevice->GetData();
        if (!NT_SUCCESS(Status) && Status != STATUS_DATA_NOT_ACCEPTED)
        {
            TraceError("CSTM %!FUNC! GetCstmData Failed %!STATUS!", Status);
        }
        WdfWaitLockRelease(pDevice->m_Lock);

        // Schedule next wake up time
        if (FALSE != pDevice->m_PoweredOn &&
            FALSE != pDevice->m_Started)
        {
            LONGLONG WaitTimeHundredNanoseconds = 0;  // in unit of 100ns

            if (0 == pDevice->m_StartTime)
            {
                // in case we fail to get sensor start time, use static wait time
                WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
            }
            else
            {
                ULONG CurrentTimeMs = 0;

                // dynamically calculate wait time to avoid jitter
                Status = GetPerformanceTime(&CurrentTimeMs);
                if (!NT_SUCCESS(Status))
                {
                    TraceError("PED %!FUNC! GetPerformanceTime %!STATUS!", Status);
                    WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
                }
                else
                {
                    WaitTimeHundredNanoseconds = pDevice->m_Interval -
                        ((CurrentTimeMs - pDevice->m_StartTime) % pDevice->m_Interval);
                    WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(WaitTimeHundredNanoseconds);
                }
            }
            WdfTimerStart(pDevice->m_Timer, WaitTimeHundredNanoseconds);
        }
    }

    SENSOR_FunctionExit(Status);
}
Ejemplo n.º 24
0
// This the completion routine of the continuous reader. This can called concurrently on multiprocessor system if there are
// more than one readers configured. So make sure to protect access to global resources.
//
void HidFx2EvtUsbInterruptPipeReadComplete(
    WDFUSBPIPE  hPipe,
    WDFMEMORY   hBuffer,
    size_t      cNumBytesTransferred,
    WDFCONTEXT  pContext
   )
{
    PDEVICE_EXTENSION   pDevContext = pContext;
    BOOLEAN             fInTimerQueue;
    unsigned char       *pbSwitchState = NULL;
    unsigned char       bCurrentSwitchState = 0;
    unsigned char       bPrevSwitchState = 0;
    unsigned char       bToggledSwitch = 0;

    UNREFERENCED_PARAMETER(cNumBytesTransferred);
    UNREFERENCED_PARAMETER(hPipe);

    TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n");

    // Interrupt endpoints sends switch state when first started  or when resuming from suspend.
    // We need to ignore that data since user did not change the switch state.
    if (pDevContext->fIsPowerUpSwitchState)
    {
        pDevContext->fIsPowerUpSwitchState = FALSE;
        TraceInfo(DBG_INIT, "(%!FUNC!) Dropping interrupt message since received during powerup/resume\n");
        return;
    }


    // Make sure that there is data in the read packet. 
    // Depending on the device specification, it is possible for it to return a 0 length read in certain conditions.
    if (cNumBytesTransferred == 0)
    {
        TraceWarning(DBG_INIT, "(%!FUNC!) Zero length read occured on the Interrupt Pipe's Continuous Reader\n");
        return;
    }

    pbSwitchState = WdfMemoryGetBuffer(hBuffer, NULL);
    bCurrentSwitchState = ~(*pbSwitchState);                // switchs are inverted on hardware boards
    bCurrentSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK;   //Mask off everything except the actual radio switch bit
    bPrevSwitchState = pDevContext->bCurrentSwitchState;

    if (bPrevSwitchState ^ bCurrentSwitchState) // make sure we toggled the radio switch
    {
        switch(pDevContext->driverMode)
        {
        // If it's a slider switch we want  0->1 and 1->0 transitions.
        case DM_SLIDER_SWITCH:
        case DM_SLIDER_SWITCH_AND_LED:
            bToggledSwitch = bCurrentSwitchState;
            // A timer is started for 10 ms everytime there is a switch toggled
            fInTimerQueue = WdfTimerStart(pDevContext->hDebounceTimer, WDF_REL_TIMEOUT_IN_MS(SWITCHPACK_DEBOUNCE_TIME));
            TraceInfo(DBG_INIT, "(%!FUNC!) Debounce Timer started. Existing -%!bool!\n", fInTimerQueue);
            break;
        //If it's a button so we only report 0->1 transitions
        case DM_BUTTON:
        case DM_BUTTON_AND_LED:
            bToggledSwitch = (bPrevSwitchState ^ bCurrentSwitchState) & bCurrentSwitchState;
            if (bToggledSwitch != 0)
            {
                // A timer is started for 10 ms everytime there is a switch toggled on
                fInTimerQueue = WdfTimerStart(pDevContext->hDebounceTimer, WDF_REL_TIMEOUT_IN_MS(SWITCHPACK_DEBOUNCE_TIME));
                TraceInfo(DBG_INIT, "(%!FUNC!) Debounce Timer started. Existing -%!bool!\n", fInTimerQueue);
            }
            break;
        // Ignore button presses if LED only
        case DM_LED_ONLY:
        default:
            break;
        }

        // Store switch state in device context
        pDevContext->bCurrentSwitchState = bCurrentSwitchState;
        pDevContext->bLatestToggledSwitch = bToggledSwitch;
    }
    else
    {
        TraceInfo(DBG_INIT, "(%!FUNC!) Not a radio switch toggle\n");
    }
    TraceInfo(DBG_INIT, "(%!FUNC!) Switch 0x%x, prevSwitch:0x%x, X0R:0x%x\n", bCurrentSwitchState, bPrevSwitchState, bToggledSwitch);

    TraceVerbose(DBG_INIT, "(%!FUNC!) Exit\n");
}
Ejemplo n.º 25
0
VOID
SimSensorAddReadRequest (
    _In_ WDFDEVICE Device,
    _In_ WDFREQUEST ReadRequest
    )

/*++

Routine Description:

    Handles IOCTL_THERMAL_READ_TEMPERATURE. If the request can be satisfied,
    it is completed immediately. Else, adds request to pending request queue.

Arguments:

    Device - Supplies a handle to the device that received the request.

    ReadRequest - Supplies a handle to the request.

--*/

{
    ULONG BytesReturned;
    PREAD_REQUEST_CONTEXT Context;
    WDF_OBJECT_ATTRIBUTES ContextAttributes;
    PFDO_DATA DevExt;
    LARGE_INTEGER ExpirationTime;
    size_t Length;
    BOOLEAN LockHeld;
    PULONG RequestTemperature;
    NTSTATUS Status;
    ULONG Temperature;
    WDFTIMER Timer;
    WDF_OBJECT_ATTRIBUTES TimerAttributes;
    WDF_TIMER_CONFIG TimerConfig;
    PTHERMAL_WAIT_READ ThermalWaitRead;


    DebugEnter();
    PAGED_CODE();

    DevExt = GetDeviceExtension(Device);
    BytesReturned = 0;
    LockHeld = FALSE;
    Status = WdfRequestRetrieveInputBuffer(ReadRequest,
                                           sizeof(THERMAL_WAIT_READ),
                                           &ThermalWaitRead,
                                           &Length);

    if (!NT_SUCCESS(Status) || Length != sizeof(THERMAL_WAIT_READ)) {

        //
        // This request is malformed, bail.
        //

        WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned);
        goto AddReadRequestEnd;
    }


    if (ThermalWaitRead->Timeout != -1 /* INFINITE */ ) {

        //
        // Estimate the system time this request will expire at.
        //

        KeQuerySystemTime(&ExpirationTime);
        ExpirationTime.QuadPart += ThermalWaitRead->Timeout * 10000;

    } else {

        //
        // Value which indicates the request never expires.
        //

        ExpirationTime.QuadPart = -1LL /* INFINITE */;
    }

    //
    // Handle the immediate timeout case in the fast path.
    //

    Temperature = SimSensorReadVirtualTemperature(Device);
    if (SimSensorAreConstraintsSatisfied(Temperature,
                                         ThermalWaitRead->LowTemperature,
                                         ThermalWaitRead->HighTemperature,
                                         ExpirationTime)) {

        Status = WdfRequestRetrieveOutputBuffer(ReadRequest,
                                                sizeof(ULONG),
                                                &RequestTemperature,
                                                &Length);

        if(NT_SUCCESS(Status) && Length == sizeof(ULONG)) {
            *RequestTemperature = Temperature;
            BytesReturned = sizeof(ULONG);

        } else {
            Status = STATUS_INVALID_PARAMETER;
            DebugPrint(SIMSENSOR_ERROR,
                       "WdfRequestRetrieveOutputBuffer() Failed. 0x%x",
                       Status);

        }

        WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned);
    } else {

        WdfWaitLockAcquire(DevExt->QueueLock, NULL);
        LockHeld = TRUE;

        //
        // Create a context to store request-specific information.
        //

        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes,
                                                READ_REQUEST_CONTEXT);

        Status = WdfObjectAllocateContext(ReadRequest,
                                          &ContextAttributes,
                                          &Context);

        if(!NT_SUCCESS(Status)) {
            DebugPrint(SIMSENSOR_ERROR,
                       "WdfObjectAllocateContext() Failed. 0x%x",
                       Status);

            WdfRequestCompleteWithInformation(ReadRequest,
                                              Status,
                                              BytesReturned);

            goto AddReadRequestEnd;
        }

        Context->ExpirationTime.QuadPart = ExpirationTime.QuadPart;
        Context->LowTemperature = ThermalWaitRead->LowTemperature;
        Context->HighTemperature = ThermalWaitRead->HighTemperature;
        if(Context->ExpirationTime.QuadPart != -1LL /* INFINITE */ ) {

            //
            // This request eventually expires, create a timer to complete it.
            //

            WDF_TIMER_CONFIG_INIT(&TimerConfig, SimSensorExpiredRequestTimer);
            WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
            TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;
            TimerAttributes.SynchronizationScope = WdfSynchronizationScopeNone;
            TimerAttributes.ParentObject = Device;
            Status = WdfTimerCreate(&TimerConfig,
                                    &TimerAttributes,
                                    &Timer);

            if(!NT_SUCCESS(Status)) {
                DebugPrint(SIMSENSOR_ERROR,
                        "WdfTimerCreate() Failed. 0x%x",
                        Status);

                WdfRequestCompleteWithInformation(ReadRequest,
                                                  Status,
                                                  BytesReturned);

                goto AddReadRequestEnd;
            }

            WdfTimerStart(Timer,
                          WDF_REL_TIMEOUT_IN_MS(ThermalWaitRead->Timeout));

        }

        Status = WdfRequestForwardToIoQueue(ReadRequest,
                                            DevExt->PendingRequestQueue);

        if(!NT_SUCCESS(Status)) {
            DebugPrint(SIMSENSOR_ERROR,
                       "WdfRequestForwardToIoQueue() Failed. 0x%x",
                       Status);

            WdfRequestCompleteWithInformation(ReadRequest,
                                              Status,
                                              BytesReturned);

            goto AddReadRequestEnd;
        }

        //
        // Force a rescan of the queue to update the interrupt thresholds.
        //

        SimSensorScanPendingQueue(Device);
    }

AddReadRequestEnd:

    if(LockHeld == TRUE) {
        WdfWaitLockRelease(DevExt->QueueLock);
    }

    DebugExitStatus(Status);
}
Ejemplo n.º 26
0
NDIS_STATUS
StaAssociate(
            __in  PSTATION        pStation,
            __in  PSTA_BSS_ENTRY  pAPEntry,
            __in  ULONG           AssociateTimeout
            )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PUCHAR              pAssocPacket = NULL;
    USHORT              AssocPacketLength;
    ULONG               StatusCode = 0;

    MpEntry;

    do {
        //
        // Create the associate packet
        //
        ndisStatus = StaCreateAssociateRequestPacket(
                                                    pStation,
                                                    pAPEntry,
                                                    &pAssocPacket,
                                                    &AssocPacketLength
                                                    );
        if (ndisStatus != NDIS_STATUS_SUCCESS) {
            //
            // Complete the association process
            //
            StatusCode = ndisStatus;
            NdisAcquireSpinLock(&(pStation->ConnectContext.Lock));
            if (pStation->ConnectContext.AssociateState == ASSOC_STATE_RECEIVED_AUTHENTICATE) {
                //
                // Reset ourselves to ready to original state
                //
                pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION;
            }
            NdisReleaseSpinLock(&(pStation->ConnectContext.Lock));

            break;
        }

        NdisAcquireSpinLock(&(pStation->ConnectContext.Lock));
        if ((pStation->ConnectContext.ConnectState >= CONN_STATE_READY_TO_CONNECT) &&
            (pStation->ConnectContext.AssociateState == ASSOC_STATE_RECEIVED_AUTHENTICATE)) {
            //
            // Packet will be sent means we will be waiting for packet response
            //
            pStation->ConnectContext.AssociateState = ASSOC_STATE_WAITING_FOR_ASSOCIATE;

            //
            // Save association request packet inside the AP entry. This will be freed
            // on association completion indication
            //
            NdisDprAcquireSpinLock(&(pAPEntry->Lock));
            pAPEntry->pAssocRequest = pAssocPacket;
            pAPEntry->AssocRequestLength = AssocPacketLength;
            NdisDprReleaseSpinLock(&(pAPEntry->Lock));

            NdisReleaseSpinLock(&(pStation->ConnectContext.Lock));
        }
        else {
            //
            // Reset, disconnect, deauthenticated by AP after authentication succeeded
            //
            NdisReleaseSpinLock(&(pStation->ConnectContext.Lock));
            MpTrace(COMP_ASSOC, DBG_LOUD, ("Reset/Disconnect/Deauth while starting association\n"));

            //
            // Assoc packet pointer isnt saved, free it
            //
            StaFreeAssociateRequestPacket(
                pStation, 
                pAPEntry, 
                pAssocPacket, 
                AssocPacketLength
                );

            //
            // Abort association 
            //
            StatusCode = (ULONG)STATUS_CANCELLED;
            break;
        }

        //
        // Send the association request packet
        //
        ndisStatus = Hw11SendMgmtPacket(
                                       pStation->pNic,
                                       pAPEntry,
                                       pAssocPacket,
                                       AssocPacketLength
                                       );
        if (ndisStatus != NDIS_STATUS_SUCCESS) {
            MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to send Association Request packet\n"));
            StatusCode = ndisStatus;

            NdisAcquireSpinLock(&(pStation->ConnectContext.Lock));
            if (pStation->ConnectContext.AssociateState == ASSOC_STATE_WAITING_FOR_AUTHENTICATE) {
                //
                // Reset ourselves to ready to original state
                //
                pStation->ConnectContext.AssociateState = ASSOC_STATE_STARTED_ASSOCIATION;
            }

            NdisReleaseSpinLock(&(pStation->ConnectContext.Lock));

            break;
        }
        else {
            // Add an extra refcount for the association timer
            STA_INCREMENT_REF(pStation->ConnectContext.AsyncFuncCount);

            //
            // Set the timeout timer for associate failure case. 
            //
            //NdisMSetTimer(&(pStation->ConnectContext.Timer_AssociateTimeout), AssociateTimeout);
            WdfTimerStart(pStation->ConnectContext.Timer_AssociateTimeout, WDF_REL_TIMEOUT_IN_MS(AssociateTimeout));

        }

        //
        // We dont let the hardware pend the request since we will be 
        // freeing the packet
        //
        MPVERIFY(ndisStatus != NDIS_STATUS_PENDING);
    }while (FALSE);

    //
    // Fail the association if we failed inline, etc
    //
    if (StatusCode != 0) {
        StaAssociateComplete(pStation, DOT11_ASSOC_STATUS_SYSTEM_ERROR);
    }

    return ndisStatus;
}
NTSTATUS AndroidUsbPipeFileObject::CommonBulkReadWrite(
    WDFREQUEST request,
    PMDL transfer_mdl,
    ULONG length,
    bool is_read,
    ULONG time_out,
    bool is_ioctl) {
  ASSERT_IRQL_LOW_OR_DISPATCH();

  ASSERT(IsPipeAttached());
  if (!IsPipeAttached()) {
    WdfRequestComplete(request, STATUS_INVALID_DEVICE_STATE);
    return STATUS_INVALID_DEVICE_STATE;
  }

  // Quick access check. Might be redundant though...
  ASSERT((is_read && is_input_pipe()) || (!is_read && is_output_pipe()));
  if ((is_read && is_output_pipe()) || (!is_read && is_input_pipe())) {
    WdfRequestComplete(request, STATUS_ACCESS_DENIED);
    return STATUS_ACCESS_DENIED;
  }

  // Set URB flags
  ULONG urb_flags = USBD_SHORT_TRANSFER_OK | (is_read ?
                                                USBD_TRANSFER_DIRECTION_IN :
                                                USBD_TRANSFER_DIRECTION_OUT);

  // Calculate transfer length for this stage.
  ULONG stage_len =
    (length > GetTransferGranularity()) ? GetTransferGranularity() : length;

  // Get virtual address that we're gonna use in the transfer.
  // We rely here on the fact that we're in the context of the calling thread.
  void* virtual_address = MmGetMdlVirtualAddress(transfer_mdl);

  // Allocate our private MDL for this address which we will use for the transfer
  PMDL new_mdl = IoAllocateMdl(virtual_address, length, FALSE, FALSE, NULL);
  ASSERT(NULL != new_mdl);
  if (NULL == new_mdl) {
    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  // Map the portion of user buffer that we're going to transfer at this stage
  // to our mdl.
  IoBuildPartialMdl(transfer_mdl, new_mdl, virtual_address, stage_len);

  // Allocate memory for URB and associate it with this request
  WDF_OBJECT_ATTRIBUTES mem_attrib;
  WDF_OBJECT_ATTRIBUTES_INIT(&mem_attrib);
  mem_attrib.ParentObject = request;

  WDFMEMORY urb_mem = NULL;
  PURB urb = NULL;
  NTSTATUS status =
    WdfMemoryCreate(&mem_attrib,
                    NonPagedPool,
                    GANDR_POOL_TAG_BULKRW_URB,
                    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                    &urb_mem,
                    reinterpret_cast<PVOID*>(&urb));
  ASSERT(NT_SUCCESS(status) && (NULL != urb));
  if (!NT_SUCCESS(status)) {
    IoFreeMdl(new_mdl);
    WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES);
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  // Get USB pipe handle for our pipe and initialize transfer request for it
  USBD_PIPE_HANDLE usbd_pipe_hndl = usbd_pipe();
  ASSERT(NULL != usbd_pipe_hndl);
  if (NULL == usbd_pipe_hndl) {
    IoFreeMdl(new_mdl);
    WdfRequestComplete(request, STATUS_INTERNAL_ERROR);
    return STATUS_INTERNAL_ERROR;
  }

  // Initialize URB with request information
  UsbBuildInterruptOrBulkTransferRequest(
    urb,
    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
    usbd_pipe_hndl,
    NULL,
    new_mdl,
    stage_len,
    urb_flags,
    NULL);

  // Build transfer request
  status = WdfUsbTargetPipeFormatRequestForUrb(wdf_pipe(),
                                               request,
                                               urb_mem,
                                               NULL);
  ASSERT(NT_SUCCESS(status));
  if (!NT_SUCCESS(status)) {
    IoFreeMdl(new_mdl);
    WdfRequestComplete(request, status);
    return status;
  }

  // Initialize our request context.
  AndroidUsbWdfRequestContext* context =
    GetAndroidUsbWdfRequestContext(request);
  ASSERT(NULL != context);
  if (NULL == context) {
    IoFreeMdl(new_mdl);
    WdfRequestComplete(request, STATUS_INTERNAL_ERROR);
    return STATUS_INTERNAL_ERROR;
  }

  context->object_type = AndroidUsbWdfObjectTypeRequest;
  context->urb_mem = urb_mem;
  context->transfer_mdl = transfer_mdl;
  context->mdl = new_mdl;
  context->length = length;
  context->transfer_size = stage_len;
  context->num_xfer = 0;
  context->virtual_address = virtual_address;
  context->is_read = is_read;
  context->initial_time_out = time_out;
  context->is_ioctl = is_ioctl;

  // Set our completion routine
  WdfRequestSetCompletionRoutine(request,
                                 CommonReadWriteCompletionEntry,
                                 this);

  // Init send options (our timeout goes here)
  WDF_REQUEST_SEND_OPTIONS send_options;
  if (0 != time_out) {
    WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_TIMEOUT);
    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&send_options, WDF_REL_TIMEOUT_IN_MS(time_out));
  }

  // Timestamp first WdfRequestSend
  KeQuerySystemTime(&context->sent_at);

  // Send request asynchronously.
  if (WdfRequestSend(request, wdf_pipe_io_target(),
                     (0 == time_out) ? WDF_NO_SEND_OPTIONS : &send_options)) {
    return STATUS_SUCCESS;
  }

  // Something went wrong here
  status = WdfRequestGetStatus(request);
  ASSERT(!NT_SUCCESS(status));
  GoogleDbgPrint("\n!!!!! CommonBulkReadWrite: WdfRequestGetStatus (is_read = %u) failed: %08X",
           is_read, status);
  WdfRequestCompleteWithInformation(request, status, 0);

  return status;
}