1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "devhost_service_full.h"
17 #include "devmgr_service_clnt.h"
18 #include "hdf_base.h"
19 #include "hdf_device_info.h"
20 #include "hdf_device_node.h"
21 #include "hdf_log.h"
22 #include "osal_message.h"
23 #include "power_state_token.h"
24
25 #define HDF_LOG_TAG devhost_service_full
26
DevHostServiceFullDispatchMessage(struct HdfMessageTask * task,struct HdfMessage * msg)27 static int32_t DevHostServiceFullDispatchMessage(struct HdfMessageTask *task, struct HdfMessage *msg)
28 {
29 struct DevHostServiceFull *hostService =
30 HDF_SLIST_CONTAINER_OF(struct HdfMessageTask, task, struct DevHostServiceFull, task);
31
32 int status = HDF_SUCCESS;
33 switch (msg->messageId) {
34 case DEVHOST_MESSAGE_ADD_DEVICE: {
35 struct HdfDeviceInfo *attribute = (struct HdfDeviceInfo *)msg->data[0];
36 status = DevHostServiceAddDevice(&hostService->super.super, attribute);
37 if (status != HDF_SUCCESS) {
38 HDF_LOGE("DevHostServiceAddDevice failed and return %{public}d", status);
39 }
40 break;
41 }
42 case DEVHOST_MESSAGE_DEL_DEVICE: {
43 devid_t devid = (devid_t)((uintptr_t)msg->data[0]);
44 status = DevHostServiceDelDevice(&hostService->super.super, devid);
45 if (status != HDF_SUCCESS) {
46 HDF_LOGE("DevHostServiceDelDevice failed and return %{public}d", status);
47 }
48 break;
49 }
50 default: {
51 HDF_LOGE("DevHostServiceFullDispatchMessage unknown message %{public}d", msg->messageId);
52 break;
53 }
54 }
55
56 return status;
57 }
58
DevHostServiceFullOpsDevice(struct IDevHostService * devHostService,uintptr_t parm,int cmdCode)59 static int DevHostServiceFullOpsDevice(struct IDevHostService *devHostService, uintptr_t parm, int cmdCode)
60 {
61 if (devHostService == NULL) {
62 HDF_LOGE("input is null");
63 return HDF_FAILURE;
64 }
65 struct DevHostServiceFull *inst = (struct DevHostServiceFull *)devHostService;
66 struct HdfMessageTask *task = &inst->task;
67 struct HdfMessage *message = HdfMessageObtain(0);
68 if (message == NULL) {
69 HDF_LOGE("HdfMessageObtain(0) return null");
70 return HDF_ERR_MALLOC_FAIL;
71 }
72
73 message->messageId = cmdCode;
74 message->data[0] = (void *)parm;
75 return task->SendMessage(task, message, true);
76 }
77
DevHostServiceFullAddDevice(struct IDevHostService * devHostService,const struct HdfDeviceInfo * attribute)78 static int DevHostServiceFullAddDevice(struct IDevHostService *devHostService, const struct HdfDeviceInfo *attribute)
79 {
80 return DevHostServiceFullOpsDevice(devHostService, (uintptr_t)attribute, DEVHOST_MESSAGE_ADD_DEVICE);
81 }
82
DevHostServiceFullDelDevice(struct IDevHostService * devHostService,devid_t devid)83 static int DevHostServiceFullDelDevice(struct IDevHostService *devHostService, devid_t devid)
84 {
85 return DevHostServiceFullOpsDevice(devHostService, (uintptr_t)devid, DEVHOST_MESSAGE_DEL_DEVICE);
86 }
87
DevHostServiceFullDispatchPowerState(struct HdfDevice * device,uint32_t state)88 static int DevHostServiceFullDispatchPowerState(struct HdfDevice *device, uint32_t state)
89 {
90 struct HdfDeviceNode *deviceNode = NULL;
91 int ret;
92 int result = HDF_SUCCESS;
93
94 if (IsPowerWakeState(state)) {
95 DLIST_FOR_EACH_ENTRY(deviceNode, &device->devNodes, struct HdfDeviceNode, entry) {
96 if (deviceNode->powerToken != NULL) {
97 ret = PowerStateChange(deviceNode->powerToken, state);
98 if (ret != HDF_SUCCESS) {
99 HDF_LOGE("device %{public}s failed to resume(%{public}d) %{public}d",
100 deviceNode->driver->entry->moduleName, state, ret);
101 result = HDF_FAILURE;
102 }
103 }
104 }
105 } else {
106 DLIST_FOR_EACH_ENTRY_REVERSE(deviceNode, &device->devNodes, struct HdfDeviceNode, entry) {
107 if (deviceNode->powerToken != NULL) {
108 ret = PowerStateChange(deviceNode->powerToken, state);
109 if (ret != HDF_SUCCESS) {
110 HDF_LOGE("device %{public}s failed to suspend(%{public}d) %{public}d",
111 deviceNode->driver->entry->moduleName, state, ret);
112 result = HDF_FAILURE;
113 }
114 }
115 }
116 }
117
118 return result;
119 }
120
SysEventToPowerState(uint32_t sysEvent)121 static uint32_t SysEventToPowerState(uint32_t sysEvent)
122 {
123 switch (sysEvent) {
124 case KEVENT_POWER_SUSPEND:
125 return POWER_STATE_SUSPEND;
126 case KEVENT_POWER_DISPLAY_OFF:
127 return POWER_STATE_DOZE_SUSPEND;
128 case KEVENT_POWER_RESUME:
129 return POWER_STATE_RESUME;
130 case KEVENT_POWER_DISPLAY_ON:
131 return POWER_STATE_DOZE_RESUME;
132 default:
133 return POWER_STATE_MAX;
134 }
135 }
136
OnSysEventReceived(struct HdfSysEventNotifyNode * self,uint64_t eventClass,uint32_t event,const char * content)137 static int OnSysEventReceived(
138 struct HdfSysEventNotifyNode *self, uint64_t eventClass, uint32_t event, const char *content)
139 {
140 (void)(content);
141 if (self == NULL) {
142 return HDF_ERR_INVALID_PARAM;
143 }
144
145 struct DevHostService *hostService = CONTAINER_OF(self, struct DevHostService, sysEventNotifyNode);
146 HDF_LOGI("host receive eventClass=%{public}llu, event=%{public}u", (unsigned long long)eventClass, event);
147 return hostService->super.PmNotify(&hostService->super, SysEventToPowerState(event));
148 }
149
DevHostServiceFullStartService(struct IDevHostService * service)150 static int DevHostServiceFullStartService(struct IDevHostService *service)
151 {
152 struct DevHostService *hostService = (struct DevHostService *)service;
153 if (hostService == NULL) {
154 HDF_LOGE("Start device service failed, hostService is null");
155 return HDF_FAILURE;
156 }
157
158 int ret = DevmgrServiceClntAttachDeviceHost(hostService->hostId, service);
159 if (ret != HDF_SUCCESS) {
160 HDF_LOGE("failed to start host service, attach host error %{public}d", ret);
161 return ret;
162 }
163
164 hostService->sysEventNotifyNode.callback = OnSysEventReceived;
165 ret = HdfSysEventNotifyRegister(&hostService->sysEventNotifyNode, HDF_SYSEVENT_CLASS_POWER);
166 if (ret != HDF_SUCCESS) {
167 HDF_LOGW("failed to register power event listener");
168 } else {
169 HDF_LOGD("host register power event listener success");
170 }
171
172 return HDF_SUCCESS;
173 }
174
DevHostServiceFullPmNotify(struct IDevHostService * service,uint32_t state)175 int DevHostServiceFullPmNotify(struct IDevHostService *service, uint32_t state)
176 {
177 struct DevHostService *hostService = (struct DevHostService *)service;
178 int result = HDF_SUCCESS;
179
180 if (hostService == NULL || !IsValidPowerState(state)) {
181 return HDF_ERR_INVALID_PARAM;
182 }
183
184 struct HdfDevice *device = NULL;
185 if (IsPowerWakeState(state)) {
186 DLIST_FOR_EACH_ENTRY_REVERSE(device, &hostService->devices, struct HdfDevice, node) {
187 if (DevHostServiceFullDispatchPowerState(device, state) != HDF_SUCCESS) {
188 result = HDF_FAILURE;
189 }
190 }
191 } else {
192 DLIST_FOR_EACH_ENTRY(device, &hostService->devices, struct HdfDevice, node) {
193 if (DevHostServiceFullDispatchPowerState(device, state)) {
194 result = HDF_FAILURE;
195 }
196 }
197 }
198
199 return result;
200 }
201
DevHostServiceFullConstruct(struct DevHostServiceFull * inst)202 void DevHostServiceFullConstruct(struct DevHostServiceFull *inst)
203 {
204 struct IDevHostService *hostServiceIf = &inst->super.super;
205 static struct IHdfMessageHandler handler = {.Dispatch = DevHostServiceFullDispatchMessage};
206 DevHostServiceConstruct(&inst->super);
207 hostServiceIf->AddDevice = DevHostServiceFullAddDevice;
208 hostServiceIf->DelDevice = DevHostServiceFullDelDevice;
209 hostServiceIf->StartService = DevHostServiceFullStartService;
210 hostServiceIf->PmNotify = DevHostServiceFullPmNotify;
211 HdfMessageLooperConstruct(&inst->looper);
212 HdfMessageTaskConstruct(&inst->task, &inst->looper, &handler);
213 }
214
DevHostServiceFullDestruct(struct DevHostServiceFull * inst)215 void DevHostServiceFullDestruct(struct DevHostServiceFull *inst)
216 {
217 if (inst != NULL) {
218 DevHostServiceDestruct(&inst->super);
219 if (inst->looper.Stop != NULL) {
220 inst->looper.Stop(&inst->looper);
221 }
222 }
223 }
224