• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "power_state_token.h"
10 #include "hdf_device_desc.h"
11 #include "hdf_slist.h"
12 #include "osal_mem.h"
13 #include "hdf_power_state.h"
14 
PowerStateTokenOnFirstAcquire(struct HdfSRef * sref)15 static void PowerStateTokenOnFirstAcquire(struct HdfSRef *sref)
16 {
17     struct PowerStateToken *stateToken = NULL;
18     if (sref == NULL) {
19         return;
20     }
21     stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF(
22         struct HdfSRef, sref, struct PowerStateToken, wakeRef);
23 
24     if (stateToken->psmState == PSM_STATE_ACTIVE) {
25         return;
26     }
27 
28     if (stateToken->psmState == PSM_STATE_INACTIVE || stateToken->psmState == PSM_STATE_IDLE) {
29         const struct IPowerEventListener *listener = stateToken->listener;
30         if ((listener != NULL) && (listener->Resume != NULL)) {
31             listener->Resume(stateToken->deviceObject);
32         }
33     }
34     stateToken->psmState = PSM_STATE_ACTIVE;
35 }
36 
PowerStateTokenOnLastRelease(struct HdfSRef * sref)37 static void PowerStateTokenOnLastRelease(struct HdfSRef *sref)
38 {
39     struct PowerStateToken *stateToken = NULL;
40     const struct IPowerEventListener *listener = NULL;
41     if (sref == NULL) {
42         return;
43     }
44     stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF(
45         struct HdfSRef, sref, struct PowerStateToken, wakeRef);
46 
47     if (stateToken->psmState != PSM_STATE_ACTIVE && stateToken->psmState != PSM_STATE_IDLE) {
48         return;
49     }
50 
51     listener = stateToken->listener;
52     if ((listener != NULL) && (listener->Suspend != NULL)) {
53         listener->Suspend(stateToken->deviceObject);
54     }
55     stateToken->psmState = PSM_STATE_INACTIVE;
56 }
57 
PowerStateChange(struct PowerStateToken * stateToken,uint32_t pEvent)58 int PowerStateChange(struct PowerStateToken *stateToken, uint32_t pEvent)
59 {
60     if (stateToken == NULL || stateToken->listener == NULL || stateToken->mode != HDF_POWER_SYS_CTRL) {
61         return HDF_SUCCESS;
62     }
63 
64     switch (pEvent) {
65         case POWER_STATE_SUSPEND:
66             if (stateToken->listener->Suspend != NULL) {
67                 return stateToken->listener->Suspend(stateToken->deviceObject);
68             }
69             break;
70         case POWER_STATE_RESUME:
71             if (stateToken->listener->Resume != NULL) {
72                 return stateToken->listener->Resume(stateToken->deviceObject);
73             }
74             break;
75         case POWER_STATE_DOZE_SUSPEND:
76             if (stateToken->listener->DozeSuspend != NULL) {
77                 return stateToken->listener->DozeSuspend(stateToken->deviceObject);
78             }
79             break;
80         case POWER_STATE_DOZE_RESUME:
81             if (stateToken->listener->DozeResume != NULL) {
82                 return stateToken->listener->DozeResume(stateToken->deviceObject);
83             }
84             break;
85         default:
86             break;
87     }
88 
89     return HDF_SUCCESS;
90 }
91 
PowerStateTokenAcquireWakeLock(struct IPowerStateToken * token)92 static void PowerStateTokenAcquireWakeLock(struct IPowerStateToken *token)
93 {
94     struct HdfSRef *sref = NULL;
95     struct PowerStateToken *stateToken = (struct PowerStateToken *)token;
96     if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) {
97         return;
98     }
99     sref = (struct HdfSRef *)&stateToken->wakeRef;
100     if ((sref != NULL) && (sref->Acquire != NULL)) {
101         sref->Acquire(sref);
102     }
103 }
104 
PowerStateTokenReleaseWakeLock(struct IPowerStateToken * token)105 static void PowerStateTokenReleaseWakeLock(struct IPowerStateToken *token)
106 {
107     struct HdfSRef *sref = NULL;
108     struct PowerStateToken *stateToken = (struct PowerStateToken *)token;
109     if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) {
110         return;
111     }
112     sref = (struct HdfSRef *)&stateToken->wakeRef;
113     if ((sref == NULL) || (sref->Release == NULL)) {
114         return;
115     }
116 
117     /* Not allowed to decrease the ref count to negative */
118     if (HdfSRefCount(sref) == 0) {
119         PowerStateTokenOnLastRelease(sref);
120     } else {
121         sref->Release(sref);
122     }
123 }
124 
PowerStateTokenConstruct(struct PowerStateToken * powerStateToken,struct HdfDeviceObject * deviceObject,const struct IPowerEventListener * listener)125 static int32_t PowerStateTokenConstruct(struct PowerStateToken *powerStateToken,
126     struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener)
127 {
128     struct IPowerStateToken *tokenIf = &powerStateToken->super;
129     struct IHdfSRefListener *srefListener = (struct IHdfSRefListener *)OsalMemCalloc(sizeof(struct IHdfSRefListener));
130     if (srefListener == NULL) {
131         return HDF_ERR_MALLOC_FAIL;
132     }
133 
134     tokenIf->AcquireWakeLock = PowerStateTokenAcquireWakeLock;
135     tokenIf->ReleaseWakeLock = PowerStateTokenReleaseWakeLock;
136 
137     srefListener->OnFirstAcquire = PowerStateTokenOnFirstAcquire;
138     srefListener->OnLastRelease = PowerStateTokenOnLastRelease;
139 
140     powerStateToken->psmState = PSM_STATE_IDLE;
141     powerStateToken->listener = listener;
142     powerStateToken->deviceObject = deviceObject;
143     HdfSRefConstruct(&powerStateToken->wakeRef, srefListener);
144 
145     return HDF_SUCCESS;
146 }
147 
PowerStateTokenNewInstance(struct HdfDeviceObject * deviceObject,const struct IPowerEventListener * listener)148 struct PowerStateToken *PowerStateTokenNewInstance(
149     struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener)
150 {
151     struct PowerStateToken *stateToken =
152         (struct PowerStateToken *)OsalMemCalloc(sizeof(struct PowerStateToken));
153     if (stateToken == NULL) {
154         return NULL;
155     }
156 
157     if (PowerStateTokenConstruct(stateToken, deviceObject, listener) != HDF_SUCCESS) {
158         OsalMemFree(stateToken);
159         return NULL;
160     }
161 
162     return stateToken;
163 }
164 
PowerStateTokenFreeInstance(struct PowerStateToken * stateToken)165 void PowerStateTokenFreeInstance(struct PowerStateToken *stateToken)
166 {
167     if (stateToken != NULL) {
168         if (stateToken->wakeRef.listener != NULL) {
169             OsalMemFree(stateToken->wakeRef.listener);
170             stateToken->wakeRef.listener = NULL;
171         }
172         OsalMemFree(stateToken);
173     }
174 }
175