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