summaryrefslogtreecommitdiff
path: root/network/wwan/cxwmbclass/power.cpp
blob: e0726975c24c972fab0e57ef355d96ce3753f41a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//
//    Copyright (C) Microsoft.  All rights reserved.
//

#include "precomp.h"

#include "power.h"
#include "device.h"
#include "adapter.h"

_Use_decl_annotations_ NTSTATUS EvtDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE previousPowerState)
{
    NTSTATUS status = STATUS_SUCCESS;
    PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
    UNREFERENCED_PARAMETER(previousPowerState);
    do
    {
        if (MbbBusIsStoped(deviceContext->BusHandle))
        {
            //
            //  device was in d3, open it again
            //
            status = MbbBusStart(deviceContext->BusHandle);

            if (!NT_SUCCESS(status))
            {
                WdfDeviceSetFailed(deviceContext->WdfDevice, WdfDeviceFailedAttemptRestart);
                break;
            }
        }
        else
        {
            MbbBusSetNotificationState(deviceContext->BusHandle, TRUE);
        }
        // Allow sessions to receive data from this point since RxQueueCreate happens later after D0Entry. We need cache NDPs receive before RxQueueCreate
        for (int i = 0; i < MBB_MAX_NUMBER_OF_SESSIONS; i++)
        {
            if (deviceContext->Sessions[i].NetAdapterContext == NULL)
            {
                continue;
            }
            deviceContext->Sessions[i].NetAdapterContext->AllowRxTraffic = TRUE;
        }
        MbbBusStartDataPipes(deviceContext->BusHandle);
    } while (FALSE);

    return status;
}

_Use_decl_annotations_ NTSTATUS EvtDeviceD0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetPowerState)
{
    UNREFERENCED_PARAMETER(TargetPowerState);
    PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);

    MbbBusStopDataPipes(deviceContext->BusHandle);
    //
    // If the device is not armed for wake, close has been sent by MbbCx. All response available notifications from close in MbbCx to EvtDeviceD0Exit will be ignored.
    //
    // If the device is armed for wake, No response available notification after EvtDeviceArmWakeFromS0 where we stop the notification.
    if (!deviceContext->m_armedWake)
    {
        MbbBusStop(deviceContext->BusHandle);
    }
    return STATUS_SUCCESS;
}

_Use_decl_annotations_ NTSTATUS EvtDevicePreviewBitmapPattern(WDFDEVICE Device, NETWAKESOURCE BitmapPattern)
{
    // We don't need to look at the pattern itself, only how many we currently have
    UNREFERENCED_PARAMETER(BitmapPattern);

    NET_WAKE_SOURCE_LIST wakeSourceList;
    NET_WAKE_SOURCE_LIST_INIT(&wakeSourceList);
    NetDeviceGetWakeSourceList(Device, &wakeSourceList);

    auto const wakeSourceCount = NetWakeSourceListGetCount(&wakeSourceList);
    size_t numberOfPowerFilters = 0;

    // Count how many power filters are currently stored for this device
    for (size_t i = 0; i < wakeSourceCount; i++)
    {
        auto wakeSource = NetWakeSourceListGetElement(&wakeSourceList, i);
        auto const wakeSourceType = NetWakeSourceGetType(wakeSource);

        if (wakeSourceType == NetWakeSourceTypeBitmapPattern)
        {
            numberOfPowerFilters++;
        }
    }

    auto const deviceContext = WmbClassGetDeviceContext(Device);
    auto const maxPowerFilters = deviceContext->BusParams.PowerFiltersSupported;

    NT_ASSERT(numberOfPowerFilters <= maxPowerFilters);

    if (numberOfPowerFilters == maxPowerFilters)
    {
        return STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL;
    }

    return STATUS_SUCCESS;
}

_Use_decl_annotations_ NTSTATUS EvtDeviceArmWakeFromS0(WDFDEVICE Device)
{
    PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
    deviceContext->m_armedWake = true;
    MbbBusSetNotificationState(deviceContext->BusHandle, FALSE);
    return STATUS_SUCCESS;
}

_Use_decl_annotations_ VOID EvtDeviceDisarmWakeFromS0(WDFDEVICE Device)
{
    PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
    deviceContext->m_armedWake = false;
}