NTSTATUS
Acpi_EnumChildren (
    _In_ PACPI_CONTEXT AcpiCtx,
    _Out_ WDFMEMORY* EnumChildrenOutput
    )
{
    NTSTATUS status;
    WDFDEVICE device;
    WDFMEMORY inputMem;
    PACPI_ENUM_CHILDREN_INPUT_BUFFER inputBuf;
    size_t inputBufSize;
    WDF_MEMORY_DESCRIPTOR inputMemDesc;
    WDFMEMORY outputMem;
    PACPI_ENUM_CHILDREN_OUTPUT_BUFFER outputBuf;
    size_t outputBufSize;
    WDF_MEMORY_DESCRIPTOR outputMemDesc;
    WDF_OBJECT_ATTRIBUTES attributes;

    PAGED_CODE();

    TRACE_FUNC_ENTRY(TRACE_FLAG_ACPI);

    device = Context_GetWdfDevice(AcpiCtx);
    inputMem = WDF_NO_HANDLE;
    outputMem = WDF_NO_HANDLE;

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

    inputBufSize = sizeof(*inputBuf);
    status = WdfMemoryCreate(&attributes,
                             NonPagedPoolNx,
                             0,
                             inputBufSize,
                             &inputMem,
                             (PVOID*) &inputBuf);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate for %Iu bytes failed", device, inputBufSize);
        goto Exit;
    }

    RtlZeroMemory(inputBuf, inputBufSize);
    inputBuf->Signature = ACPI_ENUM_CHILDREN_INPUT_BUFFER_SIGNATURE;
    inputBuf->Flags = ENUM_CHILDREN_IMMEDIATE_ONLY;

    WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemDesc, inputMem, nullptr);

    outputBufSize = sizeof(*outputBuf);

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

        status = WdfMemoryCreate(&attributes,
                                 NonPagedPoolNx,
                                 0,
                                 outputBufSize,
                                 &outputMem,
                                 (PVOID*) &outputBuf);
        if (!NT_SUCCESS(status))
        {
            TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] WdfMemoryCreate for %Iu bytes failed", device, outputBufSize);
            goto Exit;
        }

        WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMem, nullptr);

        status = WdfIoTargetSendIoctlSynchronously(WdfDeviceGetIoTarget(device),
                                                   NULL,
                                                   IOCTL_ACPI_ENUM_CHILDREN,
                                                   &inputMemDesc,
                                                   &outputMemDesc,
                                                   nullptr,
                                                   nullptr);

        if (NT_SUCCESS(status))
        {
            if (outputBuf->Signature != ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE)
            {
                status = STATUS_ACPI_INVALID_DATA;
                TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] Invalid data in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER", device);
                goto Exit;
            }

            //
            // There must be atleast one, because this device is included in the list.
            //

            if (outputBuf->NumberOfChildren < 1)
            {
                status = STATUS_ACPI_INVALID_DATA;
                TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] No child devices in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER", device);
                goto Exit;
            }

            break;
        }

        if (status != STATUS_BUFFER_OVERFLOW)
        {
            TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] IOCTL_ACPI_ENUM_CHILDREN failed - %!STATUS!", device, status);
            goto Exit;
        }

        if (outputBuf->Signature != ACPI_ENUM_CHILDREN_OUTPUT_BUFFER_SIGNATURE)
        {
            status = STATUS_ACPI_INVALID_DATA;
            TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] Invalid data in ACPI_ENUM_CHILDREN_OUTPUT_BUFFER", device);
            goto Exit;
        }

        outputBufSize = outputBuf->NumberOfChildren;
        WdfObjectDelete(outputMem);
        outputMem = WDF_NO_HANDLE;

#pragma warning(suppress:4127)
    } while (true);

    *EnumChildrenOutput = outputMem;

Exit:

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

    if (!NT_SUCCESS(status) && (outputMem != WDF_NO_HANDLE))
    {
        WdfObjectDelete(outputMem);
    }

    TRACE_FUNC_EXIT(TRACE_FLAG_ACPI);

    return status;
}
Example #2
0
NTSTATUS
ToastMon_PostWriteRequests(
    IN WDFIOTARGET IoTarget
    )
/*++

Routine Description:

    Called by the timer callback to send a write request to the target device.

Return Value:

    NT Status code

--*/
{

    WDFREQUEST                  request;
    NTSTATUS                    status;
    PTARGET_DEVICE_INFO       targetInfo;
    WDFMEMORY               memory;
    WDF_OBJECT_ATTRIBUTES       attributes;

    targetInfo = GetTargetDeviceInfo(IoTarget);

    request = targetInfo->WriteRequest;

    //
    // Allocate memory for write. Ideally I should have allocated the memory upfront along
    // with the request because the sizeof the memory buffer is constant.
    // But for demonstration, I have choosen to allocate a memory
    // object everytime I send a request down and delete it when the request
    // is completed. This memory is parented to the request.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = request;
    status = WdfMemoryCreate(
                        &attributes,
                        NonPagedPool,
                        DRIVER_TAG,
                        WRITE_BUF_SIZE,
                        &memory,
                        NULL); // buffer pointer

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

    status = WdfIoTargetFormatRequestForWrite(
                                IoTarget,
                                request,
                                memory,
                                NULL, // Buffer offset
                                NULL); // OutputBufferOffset
   if (!NT_SUCCESS(status)) {
        KdPrint(("WdfIoTargetFormatRequestForWrite failed 0x%x\n", status));
        return status;
    }

    WdfRequestSetCompletionRoutine(request,
                   Toastmon_WriteRequestCompletionRoutine,
                   targetInfo);


    //
    // Clear the WriteRequest field in the context to avoid
    // being reposted even before the reqeuest completes.
    // This will be reset in the complete routine when the request completes.
    //
    targetInfo->WriteRequest = NULL;

    if(WdfRequestSend(request, IoTarget, WDF_NO_SEND_OPTIONS) == FALSE) {
        status = WdfRequestGetStatus(request);
        KdPrint(("WdfRequestSend failed 0x%x\n", status));
        targetInfo->WriteRequest = request;
    }
    return status;
}
Example #3
0
NTSTATUS
HidFx2EvtDevicePrepareHardware(
    IN WDFDEVICE    Device,
    IN WDFCMRESLIST ResourceList,
    IN WDFCMRESLIST ResourceListTranslated
    )
/*++

Routine Description:

    In this callback, the driver does whatever is necessary to make the
    hardware ready to use.  In the case of a USB device, this involves
    reading and selecting descriptors.

Arguments:

    Device - handle to a device

    ResourceList - A handle to a framework resource-list object that
    identifies the raw hardware resourcest

    ResourceListTranslated - A handle to a framework resource-list object
    that identifies the translated hardware resources

Return Value:

    NT status value

--*/
{
    NTSTATUS                            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION                   devContext = NULL;
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    WDF_OBJECT_ATTRIBUTES               attributes;
    PUSB_DEVICE_DESCRIPTOR              usbDeviceDescriptor = NULL;

    UNREFERENCED_PARAMETER(ResourceList);
    UNREFERENCED_PARAMETER(ResourceListTranslated);

    PAGED_CODE ();

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

    devContext = GetDeviceContext(Device);
   
    //
    // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the
    // USB device descriptor and the first USB configuration descriptor from
    // the device and stores them. It also creates a framework USB interface
    // object for each interface in the device's first configuration.
    //
    // The parent of each USB device object is the driver's framework driver
    // object. The driver cannot change this parent, and the ParentObject
    // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL.
    //
    // We only create device the first time PrepareHardware is called. If 
    // the device is restarted by pnp manager for resource rebalance, we 
    // will use the same device handle but then select the interfaces again
    // because the USB stack could reconfigure the device on restart.
    //
    if (devContext->UsbDevice == NULL) {
        status = WdfUsbTargetDeviceCreate(Device,
                                          WDF_NO_OBJECT_ATTRIBUTES,
                                          &devContext->UsbDevice);
  
        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfUsbTargetDeviceCreate failed 0x%x\n", status);
            return status;
        }

        //
        // TODO: If you are fetching configuration descriptor from device for
        // selecting a configuration or to parse other descriptors, call 
        // HidFx2ValidateConfigurationDescriptor
        // to do basic validation on the descriptors before you access them.
        //

    }

    //
    // Select a device configuration by using a
    // WDF_USB_DEVICE_SELECT_CONFIG_PARAMS structure to specify USB
    // descriptors, a URB, or handles to framework USB interface objects.
    //
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE( &configParams);

    status = WdfUsbTargetDeviceSelectConfig(devContext->UsbDevice,
                                        WDF_NO_OBJECT_ATTRIBUTES,
                                        &configParams);
    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n",
            status);
        return status;
    }

    devContext->UsbInterface =
                configParams.Types.SingleInterface.ConfiguredUsbInterface;

    //
    // Get the device descriptor and store it in device context
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = Device;
    status = WdfMemoryCreate(
                             &attributes,
                             NonPagedPoolNx,
                             0,
                             sizeof(USB_DEVICE_DESCRIPTOR),
                             &devContext->DeviceDescriptor,
                             &usbDeviceDescriptor
                             );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
            "WdfMemoryCreate for Device Descriptor failed %!STATUS!\n",
            status);
        return status;
    }

    WdfUsbTargetDeviceGetDeviceDescriptor(
          devContext->UsbDevice,
          usbDeviceDescriptor
          );

    //
    // Get the Interrupt pipe. There are other endpoints but we are only
    // interested in interrupt endpoint since our HID data comes from that
    // endpoint. Another way to get the interrupt endpoint is by enumerating
    // through all the pipes in a loop and looking for pipe of Interrupt type.
    //
    devContext->InterruptPipe = WdfUsbInterfaceGetConfiguredPipe(
                                                  devContext->UsbInterface,
                                                  INTERRUPT_ENDPOINT_INDEX,
                                                  NULL);// pipeInfo

    if (NULL == devContext->InterruptPipe) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "Failed to get interrupt pipe info\n");
        status = STATUS_INVALID_DEVICE_STATE;
        return status;
    }

    //
    // Tell the framework that it's okay to read less than
    // MaximumPacketSize
    //
    WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(devContext->InterruptPipe);

    //
    //configure continuous reader
    //
    status = HidFx2ConfigContReaderForInterruptEndPoint(devContext);

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
        "HidFx2EvtDevicePrepareHardware Exit, Status:0x%x\n", status);

    return status;
}
NTSTATUS
BthEchoRepeatReaderInitialize(
    _In_ PBTHECHO_CONNECTION Connection,
    _In_ PBTHECHO_REPEAT_READER RepeatReader,
    _In_ size_t BufferSize    
    )

/*++

Description:

    This routine initializes repeat reader.

Arguments:

    Connection - Connection with which this repeat reader is associated
    RepeatReader - Repeat reader
    BufferSize - Buffer size for read

Return Value:

    NTSTATUS Status code.

--*/

{
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;

    //
    // Create request object for pending read
    // Set connection object as the parent for the request
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = WdfObjectContextGetObject(Connection);

    status = WdfRequestCreate(
        &attributes,
        Connection->DevCtxHdr->IoTarget,
        &RepeatReader->RequestPendingRead
        );                    

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, 
            "Creating request for pending read failed, "
            "Status code %!STATUS!\n",
            status
            );

        goto exit;
    }

    if (BufferSize <= 0)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER,
            "BufferSize has an invalid value: %I64d\n",
            BufferSize
            );

        status = STATUS_INVALID_PARAMETER;

        goto exit;
    }

    //
    // Create memory object for the pending read
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = RepeatReader->RequestPendingRead;

    status = WdfMemoryCreate(
        &attributes,
        NonPagedPoolNx,
        POOLTAG_BTHECHOSAMPLE,
        BufferSize,
        &RepeatReader->MemoryPendingRead,
        NULL //buffer
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, 
            "Creating memory for pending read failed, "
            "Status code %!STATUS!\n",
            status
            );

        goto exit;
    }

    //
    // Initialize Dpc that we will use for resubmitting pending read
    //
    KeInitializeDpc(
        &RepeatReader->ResubmitDpc, 
        BthEchoRepeatReaderResubmitReadDpc, 
        Connection->DevCtxHdr
        );

    //
    // Initialize event used to wait for stop.
    // This even is created as signalled. It gets cleared when
    // request is submitted.
    //
    KeInitializeEvent(&RepeatReader->StopEvent, NotificationEvent, TRUE);

    RepeatReader->Connection = Connection;
    
exit:
    if (!NT_SUCCESS(status))
    {
        BthEchoRepeatReaderUninitialize(RepeatReader);
    }
    
    return status;
}
_Use_decl_annotations_
VOID
SimBattPrepareHardware (
    WDFDEVICE Device
    )

/*++

Routine Description:

    This routine is called to initialize battery data to sane values.

    A real battery would query hardware to determine if a battery is present,
    query its static capabilities, etc.

Arguments:

    Device - Supplies the device to initialize.

Return Value:

    NTSTATUS

--*/

{

    PSIMBATT_FDO_DATA DevExt;
    WDF_OBJECT_ATTRIBUTES MemoryAttributes;
    WDFMEMORY MemoryObject;
    PSIMBATT_STATE RegState;
    NTSTATUS Status;

    DebugEnter();
    PAGED_CODE();

    DevExt = GetDeviceExtension(Device);

    //
    // Get this battery's state stored in the registry, otherwise use defaults.
    //

    RegState = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = Device;
    Status = WdfMemoryCreate(&MemoryAttributes,
                             PagedPool,
                             SIMBATT_TAG,
                             sizeof(SIMBATT_STATE),
                             &MemoryObject,
                             &((PVOID)(RegState)));

    if (!NT_SUCCESS(Status)) {
        goto SimBattPrepareHardwareEnd;
    }

    Status = GetSimBattStateFromRegistry(Device, RegState);
    if (!NT_SUCCESS(Status)) {

        RtlZeroMemory(RegState, sizeof(SIMBATT_STATE));
        WdfWaitLockAcquire(DevExt->StateLock, NULL);
        SimBattUpdateTag(DevExt);
        DevExt->State.Version = RegState->Version;
        DevExt->State.BatteryStatus.PowerState = RegState->BatteryStatus.PowerState;
        DevExt->State.BatteryStatus.Capacity = RegState->BatteryStatus.Capacity;
        DevExt->State.BatteryStatus.Voltage = RegState->BatteryStatus.Voltage;
        DevExt->State.BatteryStatus.Rate = RegState->BatteryStatus.Rate;
        DevExt->State.BatteryInfo.Capabilities = RegState->BatteryInfo.Capabilities;
        DevExt->State.BatteryInfo.Technology = RegState->BatteryInfo.Technology;
        DevExt->State.BatteryInfo.Chemistry[0] = RegState->BatteryInfo.Chemistry[0];
        DevExt->State.BatteryInfo.Chemistry[1] = RegState->BatteryInfo.Chemistry[1];
        DevExt->State.BatteryInfo.Chemistry[2] = RegState->BatteryInfo.Chemistry[2];
        DevExt->State.BatteryInfo.Chemistry[3] = RegState->BatteryInfo.Chemistry[3];
        DevExt->State.BatteryInfo.DesignedCapacity = RegState->BatteryInfo.DesignedCapacity;
        DevExt->State.BatteryInfo.FullChargedCapacity = RegState->BatteryInfo.FullChargedCapacity;
        DevExt->State.BatteryInfo.DefaultAlert1 = RegState->BatteryInfo.DefaultAlert1;
        DevExt->State.BatteryInfo.DefaultAlert2 = RegState->BatteryInfo.DefaultAlert2;
        DevExt->State.BatteryInfo.CriticalBias = RegState->BatteryInfo.CriticalBias;
        DevExt->State.BatteryInfo.CycleCount = RegState->BatteryInfo.CycleCount;
        DevExt->State.MaxCurrentDraw = RegState->MaxCurrentDraw;
        SimBattSetBatteryString(RegState->DeviceName, DevExt->State.DeviceName);
        SimBattSetBatteryString(RegState->ManufacturerName, DevExt->State.ManufacturerName);
        SimBattSetBatteryString(RegState->SerialNumber, DevExt->State.SerialNumber);
        SimBattSetBatteryString(RegState->UniqueId, DevExt->State.UniqueId);
        WdfWaitLockRelease(DevExt->StateLock);

    } else {
        WdfWaitLockAcquire(DevExt->StateLock, NULL);
        SimBattUpdateTag(DevExt);
        DevExt->State.Version = SIMBATT_STATE_VERSION;
        DevExt->State.BatteryStatus.PowerState = BATTERY_POWER_ON_LINE;
        DevExt->State.BatteryStatus.Capacity = 100;
        DevExt->State.BatteryStatus.Voltage = BATTERY_UNKNOWN_VOLTAGE;
        DevExt->State.BatteryStatus.Rate = 0;
        DevExt->State.BatteryInfo.Capabilities = BATTERY_SYSTEM_BATTERY |
                                                 BATTERY_CAPACITY_RELATIVE;

        DevExt->State.BatteryInfo.Technology = 1;
        DevExt->State.BatteryInfo.Chemistry[0] = 'F';
        DevExt->State.BatteryInfo.Chemistry[1] = 'a';
        DevExt->State.BatteryInfo.Chemistry[2] = 'k';
        DevExt->State.BatteryInfo.Chemistry[3] = 'e';
        DevExt->State.BatteryInfo.DesignedCapacity = 100;
        DevExt->State.BatteryInfo.FullChargedCapacity = 100;
        DevExt->State.BatteryInfo.DefaultAlert1 = 0;
        DevExt->State.BatteryInfo.DefaultAlert2 = 0;
        DevExt->State.BatteryInfo.CriticalBias = 0;
        DevExt->State.BatteryInfo.CycleCount = 100;
        DevExt->State.MaxCurrentDraw = UNKNOWN_CURRENT;
        SimBattSetBatteryString(DEFAULT_NAME, DevExt->State.DeviceName);
        SimBattSetBatteryString(DEFAULT_MANUFACTURER,
                                DevExt->State.ManufacturerName);

        SimBattSetBatteryString(DEFAULT_SERIALNO, DevExt->State.SerialNumber);
        SimBattSetBatteryString(DEFAULT_UNIQUEID, DevExt->State.UniqueId);
        WdfWaitLockRelease(DevExt->StateLock);

        //
        // Save new defaults to registry.
        // Normally this only happens the first time the device starts after
        // install because the key should exist after that point.
        //

        SaveSimBattStateToRegistry(Device, &DevExt->State);
    }

    if (RegState != NULL) {
        WdfObjectDelete(MemoryObject);
    }

SimBattPrepareHardwareEnd:
    DebugExitStatus(Status);
    return;
}
Example #6
0
// This routine initializes the sensor to its default properties
NTSTATUS
PedometerDevice::Initialize(
    _In_ WDFDEVICE Device, // WDFDEVICE object
    _In_ SENSOROBJECT SensorInstance // SENSOROBJECT for each sensor instance
    )
{
    ULONG Size = 0;
    WDF_OBJECT_ATTRIBUTES MemoryAttributes;
    WDFMEMORY MemoryHandle = NULL;
    FILETIME Time = {};
    WDF_OBJECT_ATTRIBUTES TimerAttributes;
    WDF_TIMER_CONFIG TimerConfig;
    NTSTATUS Status = STATUS_SUCCESS;
    PHardwareSimulator pSimulator = nullptr;
    ULONG HistorySizeInRecords = 0;

    SENSOR_FunctionEnter();

    // Store device and instance
    m_FxDevice = Device;
    m_SensorInstance = SensorInstance;
    m_Started = FALSE;
    m_HistoryRetrievalStarted = FALSE;

    // Initialize the pedometer simulator
    Status = HardwareSimulator::Initialize(Device, &m_SimulatorInstance);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", Status);
        goto Exit;
    }

    pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
        goto Exit;
    }

    // Create Lock
    Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Create timer object for polling sensor samples
    WDF_TIMER_CONFIG_INIT(&TimerConfig, PedometerDevice::OnTimerExpire);
    WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
    TimerAttributes.ParentObject = SensorInstance;
    TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! WdfTimerCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Supported Data-Fields
    Size = SENSOR_PROPERTY_LIST_SIZE(PEDOMETER_DATAFIELD_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pSupportedDataFields));
    if (!NT_SUCCESS(Status) || nullptr == m_pSupportedDataFields)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size);
    m_pSupportedDataFields->Count = PEDOMETER_DATAFIELD_COUNT;

    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_TIMESTAMP] = PKEY_SensorData_Timestamp;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_FIRST_AFTER_RESET] = PKEY_SensorData_PedometerReset;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_TYPE] = PKEY_SensorData_PedometerStepType;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_COUNT] = PKEY_SensorData_PedometerStepCount;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_DURATION] = PKEY_SensorData_PedometerStepDuration_Ms;

    // Data
    Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_DATA_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pData));
    if (!NT_SUCCESS(Status) || nullptr == m_pData)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pData, Size);
    m_pData->Count = PEDOMETER_DATA_COUNT;

    m_pData->List[PEDOMETER_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
    GetSystemTimePreciseAsFileTime(&Time);
    InitPropVariantFromFileTime(&Time, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value));

    m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Key = PKEY_SensorData_PedometerReset;
    InitPropVariantFromBoolean(FALSE, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Unknown), &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(600, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(123, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Walking), &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(700, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(456, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Running), &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(800, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(789, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value));

    m_LastSample.Timestamp = Time;
    m_LastSample.UnknownStepCount = 0;
    m_LastSample.UnknownStepDurationMs = 0;
    m_LastSample.WalkingStepCount = 0;
    m_LastSample.WalkingStepDurationMs = 0;
    m_LastSample.RunningStepCount = 0;
    m_LastSample.RunningStepDurationMs = 0;
    m_LastSample.IsFirstAfterReset = FALSE;

    // Get the History Size to populate 'PKEY_SensorHistory_MaxSize_Bytes'
    // Typically the size needed to store a history record on the hardware is 
    // smaller than the size needed to represent a history record as a 
    // SENSOR_COLLECTION_LIST (collection of SENSOR_VALUE_PAIRs)
    // To be able to accurately represent the size of the history on the 
    // hardware (simulator in this case), get the number of records that the HW  
    // can store and multiply it with the marshalled size of 
    // SENSOR_COLLECTION_LIST needed to represent a single record.

    HistorySizeInRecords = pSimulator->GetHistorySizeInRecords();
    m_HistorySupported = (HistorySizeInRecords > 0) ? TRUE : FALSE;

    // Pedometer History format is exactly same as it's data sample.
    // so, we can simply reuse the 'm_pData' to compute the marshalled size
    // History Retrieval is not WOW64 compatible and hence will not involve 
    // serializing the collections list. Should Use 
    // CollectionsListGetMarshalledSizeWithoutSerialization  instead of 
    // CollectionsListGetMarshalledSize when dealing with History Collection list.
    m_HistoryMarshalledRecordSize = CollectionsListGetMarshalledSizeWithoutSerialization(m_pData);

    // Sensor Enumeration Properties
    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ENUMERATION_PROPERTIES_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes,
        PagedPool,
        SENSOR_POOL_TAG_PEDOMETER,
        Size,
        &MemoryHandle,
        reinterpret_cast<PVOID*>(&m_pEnumerationProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, Size);
    m_pEnumerationProperties->Count = SENSOR_ENUMERATION_PROPERTIES_COUNT;

    m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type;
    InitPropVariantFromCLSID(GUID_SensorType_Pedometer,
        &(m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Value));

    m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer;
    InitPropVariantFromString(L"Microsoft",
        &(m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Value));

    m_pEnumerationProperties->List[SENSOR_MODEL].Key = DEVPKEY_Sensor_Model;
    InitPropVariantFromString(L"PEDOMETER",
        &(m_pEnumerationProperties->List[SENSOR_MODEL].Value));

    m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId;
    InitPropVariantFromCLSID(GUID_PedometerDevice_UniqueID,
        &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value));

    m_pEnumerationProperties->List[SENSOR_CATEGORY].Key = DEVPKEY_Sensor_Category;
    InitPropVariantFromCLSID(GUID_SensorCategory_Motion,
        &(m_pEnumerationProperties->List[SENSOR_CATEGORY].Value));

    m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary;
    InitPropVariantFromBoolean(FALSE,
        &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Value)); // This value should be set to TRUE if multiple pedometers
                                                                    // exist on the system and this sensor is the primary sensor

    m_pEnumerationProperties->List[SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
    InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts,
        &(m_pEnumerationProperties->List[SENSOR_POWER].Value));

    m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
    InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ?
        (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) :
        0),
        &(m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Value));

    m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes;
    InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running,
        &(m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Value));

    // Sensor Properties
    m_Interval = Pedometer_Default_MinDataInterval_Ms;

    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTIES_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size);
    m_pProperties->Count = SENSOR_COMMON_PROPERTIES_COUNT;

    m_pProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State;
    InitPropVariantFromUInt32(SensorState_Initializing, 
                              &(m_pProperties->List[SENSOR_PROPERTY_STATE].Value));

    m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms;
    InitPropVariantFromUInt32(Pedometer_Default_MinDataInterval_Ms, 
                              &(m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes;
    InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pData), 
                              &(m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Key = PKEY_Sensor_Type;
    InitPropVariantFromCLSID(GUID_SensorType_Pedometer, 
                                 &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
    InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts,
                                &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
    InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ?
                                (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) :
                                0),
                                &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Key = PKEY_SensorHistory_Interval_Ms;
    InitPropVariantFromUInt32(pSimulator->GetHistoryIntervalInMs(),
                                &(m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Key = PKEY_SensorHistory_MaximumRecordSize_Bytes;
    InitPropVariantFromUInt32(m_HistoryMarshalledRecordSize,
        &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes;
    InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running,
        &(m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Value));

    // Data field properties
    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT);
    
    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pDataFieldProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pDataFieldProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pDataFieldProperties, Size);
    m_pDataFieldProperties->Count = SENSOR_DATA_FIELD_PROPERTY_COUNT;

    m_pDataFieldProperties->List[SENSOR_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
    InitPropVariantFromInt64(PedometerDevice_StepCount_Resolution,
                             &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value));

    m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum;
    InitPropVariantFromUInt32(PedometerDevice_StepCount_Minimum,
                             &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value));

    m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum;
    InitPropVariantFromUInt32(PedometerDevice_StepCount_Maximum,
                             &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value));

    // Set default threshold
    m_FirstSample = TRUE;

    Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_THRESHOLD_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes,
                             PagedPool,
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pThresholds));
    if (!NT_SUCCESS(Status) || nullptr == m_pThresholds)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size);
    m_pThresholds->Count = PEDOMETER_THRESHOLD_COUNT;

    m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(Pedometer_Default_Threshold_StepCount,
                             &(m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Value));

    m_CachedThreshold = Pedometer_Default_Threshold_StepCount;
Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Example #7
0
// In this callback, the driver does whatever is necessary to make the hardware ready to use.
// In the case of a USB device, this involves reading and selecting descriptors.
NTSTATUS
HidFx2EvtDevicePrepareHardware(
    _In_ WDFDEVICE    hDevice,
    _In_ WDFCMRESLIST hResourceList,
    _In_ WDFCMRESLIST hResourceListTranslated
   )
{
    NTSTATUS                            status = STATUS_SUCCESS;
    PDEVICE_EXTENSION                   pDevContext = NULL;
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
    WDF_OBJECT_ATTRIBUTES               attributes;
    PUSB_DEVICE_DESCRIPTOR              pUsbDeviceDescriptor = NULL;

    UNREFERENCED_PARAMETER(hResourceList);
    UNREFERENCED_PARAMETER(hResourceListTranslated);

    PAGED_CODE ();

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

    pDevContext = GetDeviceContext(hDevice);

    // Create a WDFUSBDEVICE object. WdfUsbTargetDeviceCreate obtains the USB device descriptor and the first USB configuration
    //descriptor from the device and stores them. It also creates a framework USB interface object for each interface in the device's first configuration.
    //
    // The parent of each USB device object is the driver's framework driver object. The driver cannot change this parent, and the ParentObject
    // member or the WDF_OBJECT_ATTRIBUTES structure must be NULL.
    //
    // We only create device the first time PrepareHardware is called. If the device is restarted by pnp manager for resource rebalance, we 
    // will use the same device handle but then select the interfaces again because the USB stack could reconfigure the device on restart.
    if (pDevContext->hUsbDevice == NULL)
    {
        status = WdfUsbTargetDeviceCreate(hDevice, WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->hUsbDevice);
        if (!NT_SUCCESS(status))
        {
            TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceCreate failed %!STATUS!\n", status);
            return status;
        }
    }

    // Select a device configuration by using a WDF_USB_DEVICE_SELECT_CONFIG_PARAMS
    WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE(&configParams);
    status = WdfUsbTargetDeviceSelectConfig(pDevContext->hUsbDevice, WDF_NO_OBJECT_ATTRIBUTES, &configParams);
    if (!NT_SUCCESS(status))
    {
        TraceErr(DBG_PNP, "(%!FUNC!) WdfUsbTargetDeviceSelectConfig failed %!STATUS!\n", status);
        return status;
    }

    pDevContext->hUsbInterface = configParams.Types.SingleInterface.ConfiguredUsbInterface;

    // Get the device descriptor and store it in device context
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = hDevice;
    status = WdfMemoryCreate(&attributes,
                             NonPagedPool,
                             0,
                             sizeof(USB_DEVICE_DESCRIPTOR),
                             &pDevContext->hDeviceDescriptor,
                             &pUsbDeviceDescriptor);
    if (!NT_SUCCESS(status))
    {
        TraceErr(DBG_PNP, "(%!FUNC!) WdfMemoryCreate for Device Descriptor failed %!STATUS!\n", status);
        return status;
    }

    WdfUsbTargetDeviceGetDeviceDescriptor(pDevContext->hUsbDevice, pUsbDeviceDescriptor);

    // Get the Interrupt pipe. There are other endpoints but we are only interested in interrupt endpoint since our HID data comes from this
    pDevContext->hInterruptPipe = WdfUsbInterfaceGetConfiguredPipe(pDevContext->hUsbInterface, INTERRUPT_ENDPOINT_INDEX, NULL);
    if (NULL == pDevContext->hInterruptPipe)
    {
        TraceErr(DBG_PNP, "(%!FUNC!) Failed to get interrupt pipe info\n");
        status = STATUS_INVALID_DEVICE_STATE;
        return status;
    }

    // Tell the framework that it's okay to read less than MaximumPacketSize
    WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(pDevContext->hInterruptPipe);

    //configure continuous reader
    status = HidFx2ConfigContReaderForInterruptEndPoint(pDevContext);

    TraceVerbose(DBG_INIT, "(%!FUNC!) Exit, Status: %!STATUS!\n", status);

    return status;
}
Example #8
0
VOID
ReadWriteBulkEndPoints(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN ULONG            Length,
    IN WDF_REQUEST_TYPE RequestType
    )
/*++

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

--*/
{
    PMDL                    newMdl=NULL, 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;

    kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - begins\n"));

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

    if (totalLength > deviceContext->MaximumTransferSize) {
        kJtag_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        kJtag_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        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)) {
        kJtag_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt\n"));
        status = STATUS_INVALID_DEVICE_REQUEST;
        goto Exit;

    }

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead) {

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

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        rwContext->Read = TRUE;
        kJtag_DbgPrint(3, ("Read operation\n"));

    } else {
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status)){
            kJtag_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed %x\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        rwContext->Read = FALSE;
        kJtag_DbgPrint(3, ("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) {
        kJtag_DbgPrint(1, ("Failed to alloc mem for mdl\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)) {
        kJtag_DbgPrint(1, ("Failed to alloc mem for urb\n"));
        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)) {
        kJtag_DbgPrint(1, ("Failed to format requset for urb\n"));
        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;

    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);
        }
    }

    kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - ends\n"));

    return;
}
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;
}
NTSTATUS
Acpi_EvaluatePld (
    _In_ PACPI_CONTEXT AcpiCtx,
    _In_ LPCSTR DeviceName,
    _Out_ PACPI_PLD_BUFFER PldBuffer
    )
{
    NTSTATUS status;
    WDFDEVICE device;
    WDF_MEMORY_DESCRIPTOR inputMemDesc;
    ACPI_EVAL_INPUT_BUFFER_EX inputBuffer;
    size_t inputBufferSize;
    WDFMEMORY outputMemory;
    WDF_MEMORY_DESCRIPTOR outputMemDesc;
    PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    size_t outputBufferSize;
    size_t outputArgumentBufferSize;
    WDF_OBJECT_ATTRIBUTES attributes;

    PAGED_CODE();

    TRACE_FUNC_ENTRY(TRACE_FLAG_ACPI);

    device = Context_GetWdfDevice(AcpiCtx);
    outputMemory = WDF_NO_HANDLE;

    inputBufferSize = sizeof(inputBuffer);
    RtlZeroMemory(&inputBuffer, inputBufferSize);

    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX;

    status = RtlStringCchPrintfA(inputBuffer.MethodName,
                                 sizeof(inputBuffer.MethodName),
                                 "%s._PLD",
                                 DeviceName);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] RtlStringCchPrintfA for creating method name failed - %!STATUS!", device, status);
        goto Exit;
    }

    outputArgumentBufferSize = 1024;
    outputBufferSize =
        FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) +
        outputArgumentBufferSize;

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

    status = WdfMemoryCreate(&attributes,
                             NonPagedPoolNx,
                             0,
                             outputBufferSize,
                             &outputMemory,
                             (PVOID*) &outputBuffer);

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

    RtlZeroMemory(outputBuffer, outputBufferSize);

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, &inputBuffer, (ULONG) inputBufferSize);
    WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL);

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

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

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

    if (outputBuffer->Count < 1)
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] _PLD for %s didn't return anything", device, inputBuffer.MethodName);
        goto Exit;
    }

    if (outputBuffer->Argument[0].Type != ACPI_METHOD_ARGUMENT_BUFFER)
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] _PLD for %s returned an unexpected argument of type %d", device, inputBuffer.MethodName, outputBuffer->Argument[0].Type);
        goto Exit;
    }

    if (outputBuffer->Argument[0].DataLength < sizeof(*PldBuffer))
    {
        status = STATUS_ACPI_INVALID_DATA;
        TRACE_ERROR(TRACE_FLAG_ACPI, "[Device: 0x%p] Unexpected _PLD buffer size for %s. Expected %Iu bytes, got %Iu bytes", device, inputBuffer.MethodName, sizeof(*PldBuffer), outputBuffer->Argument[0].DataLength);
        goto Exit;
    }

    *PldBuffer = *((PACPI_PLD_BUFFER) outputBuffer->Argument[0].Data);

Exit:

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

    TRACE_FUNC_EXIT(TRACE_FLAG_ACPI);

    return status;
}
Example #11
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;
}
Example #12
0
static VOID UsbChief_ReadEndPoint(IN WDFQUEUE Queue, IN WDFREQUEST Request,
			   IN ULONG totalLength)
{
	PMDL                    newMdl=NULL, requestMdl = NULL;
	PURB                    urb = NULL;
	WDFMEMORY               urbMemory;
	ULONG                   stageLength = 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;

	UsbChief_DbgPrint(DEBUG_RW, ("UsbChief_DispatchReadWrite - begins\n"));

	deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
	fileContext = GetFileContext(WdfRequestGetFileObject(Request));
	pipe = fileContext->Pipe;

	WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
	WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

	rwContext = GetRequestContext(Request);

	status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
	if(!NT_SUCCESS(status)){
		UsbChief_DbgPrint(0, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status));
		goto Exit;
	}
	virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

	if (totalLength > MAX_TRANSFER_SIZE)
		stageLength = MAX_TRANSFER_SIZE;
	else
		stageLength = totalLength;

	newMdl = IoAllocateMdl((PVOID) virtualAddress, totalLength,
			       FALSE, FALSE, NULL);

	if (!newMdl) {
		UsbChief_DbgPrint(0, ("Failed to alloc mem for mdl\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	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)) {
		UsbChief_DbgPrint(0, ("Failed to alloc mem for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

	UsbBuildInterruptOrBulkTransferRequest(urb,
					       sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
					       usbdPipeHandle,
					       NULL,
					       newMdl,
					       stageLength,
					       USBD_TRANSFER_DIRECTION_IN |
					       USBD_SHORT_TRANSFER_OK,
					       NULL);

	status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL  );
	if (!NT_SUCCESS(status)) {
		UsbChief_DbgPrint(0, ("Failed to format requset for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}
	WdfRequestSetCompletionRoutine(Request, UsbChief_ReadCompletion, NULL);

	rwContext->UrbMemory       = urbMemory;
	rwContext->Mdl             = newMdl;
	rwContext->Length          = totalLength - stageLength;
	rwContext->Numxfer         = 0;
	rwContext->VirtualAddress  = virtualAddress + stageLength;

	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);
		}
	}
}
Example #13
0
static NTSTATUS CyGetUSB30DeviceConfiguration(__in PDEVICE_CONTEXT pDevContext,WDFMEMORY *pUsb30DeviceConfig)
{/* WdfUsbTargetDeviceRetrieveConfigDescriptor function return the selected interface detail while the 
    WdfUsbTargetDeviceFormatRequestForControlTransfer function return the device whole configuration(including the multiple interface)
    which is we don't want, adding specific implementation for the getting configuration descriptor here*/						
	USHORT  ConfigLen = 0;
	PUSB_CONFIGURATION_DESCRIPTOR  configurationDescriptor = NULL;
	WDF_OBJECT_ATTRIBUTES  objectAttribs;	
	NTSTATUS NtStatus =STATUS_SUCCESS;
	WDF_USB_CONTROL_SETUP_PACKET  controlSetupPacket;
	WDF_MEMORY_DESCRIPTOR  tmpmemoryDescriptor;
	WDF_MEMORY_DESCRIPTOR  tmpmemoryDescriptor1;
    USB_CONFIGURATION_DESCRIPTOR  UsbConfigDec;


	CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Start CyGetUSB30DeviceConfiguration\n");
	
	// first get the configuration length
	//Initialze the buffer
	WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&tmpmemoryDescriptor,
                                  (PVOID) &UsbConfigDec,
                                  sizeof(USB_CONFIGURATION_DESCRIPTOR));

	//Initialize control setup packet to get total configuration  length.
	controlSetupPacket.Packet.bm.Request.Dir = BmRequestDeviceToHost ;
	controlSetupPacket.Packet.bm.Request.Type = BmRequestStandard;
	controlSetupPacket.Packet.bm.Request.Recipient = BmRequestToDevice;
	controlSetupPacket.Packet.bRequest = USB_REQUEST_GET_DESCRIPTOR;
	controlSetupPacket.Packet.wIndex.Bytes.HiByte = 0;
	controlSetupPacket.Packet.wIndex.Bytes.LowByte = 0;
	controlSetupPacket.Packet.wValue.Bytes.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
	controlSetupPacket.Packet.wValue.Bytes.LowByte =0;
	controlSetupPacket.Packet.wLength  = sizeof(USB_CONFIGURATION_DESCRIPTOR);

    NtStatus = WdfUsbTargetDeviceSendControlTransferSynchronously(
                                         pDevContext->CyUsbDevice,
                                         WDF_NO_HANDLE,
                                         NULL,
                                         &controlSetupPacket,
                                         &tmpmemoryDescriptor,
                                         NULL
                                         );
	if (!NT_SUCCESS(NtStatus)) 
	{
		CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSendControlTransferSynchronously failed:%x \n",NtStatus);		
		CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyGetUSB30DeviceConfiguration\n");
		return NtStatus;
	}
	// allocate memory to get the device configuration
	WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
	objectAttribs.ParentObject = pDevContext->CyUsbDevice;
	// This object will be deleted after 
	NtStatus = WdfMemoryCreate(
							   &objectAttribs,
							   NonPagedPool,
							   CYMEM_TAG,
							   UsbConfigDec.wTotalLength,
							   pUsb30DeviceConfig,
							   (PVOID)&configurationDescriptor
							   );
	if (!NT_SUCCESS(NtStatus)) {
		CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfMemoryCreate failed:%x \n",NtStatus);		
		CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyGetUSB30DeviceConfiguration\n");
		return NtStatus;
	}
	WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&tmpmemoryDescriptor1,
                                  *pUsb30DeviceConfig,
                                  NULL);


	//Get whole device configuration using the wTotalLenght od configuration descriptor
	//Initialize control setup packet to get total configuration  length.
	controlSetupPacket.Packet.bm.Request.Dir = BmRequestDeviceToHost ;
	controlSetupPacket.Packet.bm.Request.Type = BmRequestStandard;
	controlSetupPacket.Packet.bm.Request.Recipient = BmRequestToDevice ;
	controlSetupPacket.Packet.bRequest = USB_REQUEST_GET_DESCRIPTOR;
	controlSetupPacket.Packet.wIndex.Bytes.HiByte = 0;
	controlSetupPacket.Packet.wIndex.Bytes.LowByte = 0;
	controlSetupPacket.Packet.wValue.Bytes.HiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE;
	controlSetupPacket.Packet.wValue.Bytes.LowByte =0;
	controlSetupPacket.Packet.wLength  = UsbConfigDec.wTotalLength;

    NtStatus = WdfUsbTargetDeviceSendControlTransferSynchronously(
                                         pDevContext->CyUsbDevice,
                                         WDF_NO_HANDLE,
                                         NULL,
                                         &controlSetupPacket,
                                         &tmpmemoryDescriptor1,
                                         NULL
                                         );
	if (!NT_SUCCESS(NtStatus)) 
	{
		CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfUsbTargetDeviceSendControlTransferSynchronously failed:%x \n",NtStatus);		
		CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyGetUSB30DeviceConfiguration\n");
		return NtStatus;
	}

	CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyGetUSB30DeviceConfiguration\n");
	return NtStatus;
}
Example #14
0
NTSTATUS
  CyEvtDevicePrepareHardware (
    IN WDFDEVICE  Device,
    IN WDFCMRESLIST  ResourcesRaw,
    IN WDFCMRESLIST  ResourcesTranslated
    )
{
	NTSTATUS  NTStatus;
	PDEVICE_CONTEXT  pDeviceContext;
	WDF_USB_DEVICE_INFORMATION UsbDeviceInfo;
    ULONG ulWaitWakeEnable;

	UNICODE_STRING unicodeSCRIPTFILE;	
	WDF_OBJECT_ATTRIBUTES  attributes;
	WDFMEMORY  hScriptFileNameBufMem;
	PVOID  pScriptFNBuf=NULL;
	ULONG ScripFileNtBufferlen=0;

	UNREFERENCED_PARAMETER(ResourcesRaw);
    UNREFERENCED_PARAMETER(ResourcesTranslated);
    ulWaitWakeEnable = FALSE;

    PAGED_CODE();

    CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "Start CyEvtDevicePrepareHardware\n");

    pDeviceContext = CyGetDeviceContext(Device);

	//
    // Create a USB device handle so that we can communicate with the
    // underlying USB stack. The WDFUSBDEVICE handle is used to query,
    // configure, and manage all aspects of the USB device.
    // These aspects include device properties, bus properties,
    // and I/O creation and synchronization. We only create device the first
    // the PrepareHardware is called. If the device is restarted by pnp manager
    // for resource rebalance, we will use the same device handle but then select
    // the interfaces again because the USB stack could reconfigure the device on
    // restart.
    //	
    if (pDeviceContext->CyUsbDevice == NULL)
	{
        NTStatus = WdfUsbTargetDeviceCreate(Device,
                                    WDF_NO_OBJECT_ATTRIBUTES,
                                    &pDeviceContext->CyUsbDevice);
        if (!NT_SUCCESS(NTStatus)) {
            CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                 "WdfUsbTargetDeviceCreate failed with Status code %!STATUS!\n", NTStatus);
            return NTStatus;
        }
    }    

	 //
    // Retrieve USBD version information, port driver capabilites and device
    // capabilites such as speed, power, etc.
    //
    WDF_USB_DEVICE_INFORMATION_INIT(&UsbDeviceInfo);

    NTStatus = WdfUsbTargetDeviceRetrieveInformation(
                                pDeviceContext->CyUsbDevice,
                                &UsbDeviceInfo);
    if (NT_SUCCESS(NTStatus))
	{
        CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IsDeviceHighSpeed: %s\n",
            (UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED) ? "TRUE" : "FALSE");
        CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                    "IsDeviceSelfPowered: %s\n",
            (UsbDeviceInfo.Traits & WDF_USB_DEVICE_TRAIT_SELF_POWERED) ? "TRUE" : "FALSE");

        ulWaitWakeEnable = UsbDeviceInfo.Traits &
                            WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;

        CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,
                            "IsDeviceRemoteWakeable: %s\n",
                            ulWaitWakeEnable ? "TRUE" : "FALSE");
        
        pDeviceContext->ulUSBDeviceTrait = UsbDeviceInfo.Traits;
		pDeviceContext->ulUSBDIVersion = UsbDeviceInfo.UsbdVersionInformation.USBDI_Version;
		pDeviceContext->ulWaitWakeEnable = ulWaitWakeEnable;
    }   
	
	//Get device descriptor
	WdfUsbTargetDeviceGetDeviceDescriptor(
									  pDeviceContext->CyUsbDevice,
									  &pDeviceContext->UsbDeviceDescriptor
									  );
	
    NTStatus = CySelectInterfaces(Device);

    if (!NT_SUCCESS(NTStatus))
	{
        CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                    "SelectInterfaces failed 0x%x\n", NTStatus);

        return NTStatus;
    }
   
	if (ulWaitWakeEnable)
	{
        NTStatus = CySetPowerPolicy(Device);
        if (!NT_SUCCESS (NTStatus)) 
		{
            CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                                "Set power policy failed  %!STATUS!\n", NTStatus);
            return NTStatus;
        }
    }
	// Check for the script file in the registry and execute if it is exist
	
	// Allocate buffer to get the registry key
	WDF_OBJECT_ATTRIBUTES_INIT(&attributes);	
	NTStatus = WdfMemoryCreate(
							 &attributes,
							 NonPagedPool,
							 0,
							 CYREGSCRIPT_BUFFER_SIZE,
							 &hScriptFileNameBufMem,
							 &pScriptFNBuf
							 );
	if (!NT_SUCCESS(NTStatus)) {
		CyTraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfMemoryCreate failed  %!STATUS!\n",NTStatus);        
		return FALSE;
	}

	
    if(GetRegistryKey(Device, NULL, REG_SZ, CYREG_SCRIPTFILE, pScriptFNBuf,&ScripFileNtBufferlen)) 
    {	
        CyExecuteScriptFile(Device, pScriptFNBuf);
    }
	CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDevicePrepareHardware\n");		
        
	////
	CyTraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "End CyEvtDevicePrepareHardware\n");	
	return NTStatus;
}
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;
}