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