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