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 "devhost_service.h"
10 #include "devmgr_service_clnt.h"
11 #include "hdf_base.h"
12 #include "hdf_driver.h"
13 #include "hdf_driver_loader.h"
14 #include "hdf_log.h"
15 #include "hdf_object_manager.h"
16 #include "osal_mem.h"
17 #include "power_state_token.h"
18
19 #define HDF_LOG_TAG devhost_service
20
DevHostServiceFindDevice(struct DevHostService * hostService,uint16_t deviceId)21 static struct HdfDevice *DevHostServiceFindDevice(struct DevHostService *hostService, uint16_t deviceId)
22 {
23 struct HdfDevice *device = NULL;
24 if (hostService == NULL) {
25 HDF_LOGE("failed to find driver, hostService is null");
26 return NULL;
27 }
28
29 DLIST_FOR_EACH_ENTRY(device, &hostService->devices, struct HdfDevice, node) {
30 if (DEVICEID(device->deviceId) == deviceId) {
31 return device;
32 }
33 }
34 return NULL;
35 }
36
DevHostServiceFreeDevice(struct DevHostService * hostService,struct HdfDevice * device)37 static void DevHostServiceFreeDevice(struct DevHostService *hostService, struct HdfDevice *device)
38 {
39 (void)hostService;
40 if (device != NULL) {
41 DListRemove(&device->node);
42 HdfDeviceFreeInstance(device);
43 }
44 }
45
DevHostServiceQueryOrAddDevice(struct DevHostService * inst,uint16_t deviceId)46 static struct HdfDevice *DevHostServiceQueryOrAddDevice(struct DevHostService *inst, uint16_t deviceId)
47 {
48 struct HdfDevice *device = DevHostServiceFindDevice(inst, deviceId);
49 if (device == NULL) {
50 HDF_LOGD("%{public}s can't find device, try to create", __func__);
51 device = HdfDeviceNewInstance();
52 if (device == NULL) {
53 HDF_LOGE("Dev host service failed to create driver instance");
54 return NULL;
55 }
56 device->deviceId = MK_DEVID(inst->hostId, deviceId, 0);
57 DListInsertHead(&device->node, &inst->devices);
58 HDF_LOGD("%{public}s add device complete", __func__);
59 }
60 return device;
61 }
62
DevHostServiceAddDevice(struct IDevHostService * inst,const struct HdfDeviceInfo * deviceInfo)63 int DevHostServiceAddDevice(struct IDevHostService *inst, const struct HdfDeviceInfo *deviceInfo)
64 {
65 int ret = HDF_FAILURE;
66 struct HdfDevice *device = NULL;
67 struct HdfDeviceNode *devNode = NULL;
68 struct HdfDriver *driver = NULL;
69 struct DevHostService *hostService = CONTAINER_OF(inst, struct DevHostService, super);
70 struct IDriverLoader *driverLoader = HdfDriverLoaderGetInstance();
71
72 if (inst == NULL || deviceInfo == NULL || driverLoader == NULL || driverLoader->GetDriver == NULL) {
73 HDF_LOGE("failed to add device, input param is null");
74 return ret;
75 }
76
77 device = DevHostServiceQueryOrAddDevice(hostService, DEVICEID(deviceInfo->deviceId));
78 if (device == NULL || device->super.Attach == NULL) {
79 HDF_LOGE("failed to add device, device or Attach func is null");
80 return HDF_DEV_ERR_NO_DEVICE;
81 }
82 devNode = device->super.GetDeviceNode(&device->super, deviceInfo->deviceId);
83 if (devNode != NULL) {
84 HDF_LOGE("failed to add device, device already exist");
85 return HDF_ERR_DEVICE_BUSY;
86 }
87 driver = driverLoader->GetDriver(deviceInfo->moduleName);
88 if (driver == NULL) {
89 HDF_LOGE("failed to add device %{public}s, get driver failed", deviceInfo->moduleName);
90 ret = HDF_DEV_ERR_NODATA;
91 goto ERROR;
92 }
93
94 devNode = HdfDeviceNodeNewInstance(deviceInfo, driver);
95 if (devNode == NULL) {
96 HDF_LOGE("failed to add device, create devNode failed");
97 driverLoader->ReclaimDriver(driver);
98 return HDF_DEV_ERR_NO_MEMORY;
99 }
100
101 devNode->hostService = hostService;
102 devNode->device = device;
103 devNode->driver = driver;
104 ret = device->super.Attach(&device->super, devNode);
105 if (ret != HDF_SUCCESS) {
106 HDF_LOGE("failed to add device, attach devNode failed");
107 HdfDeviceNodeFreeInstance(devNode);
108 goto ERROR;
109 }
110 HDF_LOGD("%{public}s add device success", __func__);
111 return HDF_SUCCESS;
112
113 ERROR:
114 if (DListIsEmpty(&device->devNodes)) {
115 DevHostServiceFreeDevice(hostService, device);
116 }
117
118 return ret;
119 }
120
DevHostServiceDelDevice(struct IDevHostService * inst,devid_t devId)121 int DevHostServiceDelDevice(struct IDevHostService *inst, devid_t devId)
122 {
123 struct HdfDevice *device = NULL;
124 struct DevHostService *hostService = (struct DevHostService *)inst;
125 struct HdfDeviceNode *devNode = NULL;
126
127 device = DevHostServiceFindDevice(hostService, DEVICEID(devId));
128 if (device == NULL) {
129 HDF_LOGW("failed to del device, device is not exist");
130 return HDF_SUCCESS;
131 }
132
133 devNode = device->super.GetDeviceNode(&device->super, devId);
134 if (devNode == NULL) {
135 HDF_LOGI("failed to del device, not exist");
136 return HDF_DEV_ERR_NO_DEVICE;
137 }
138
139 if (device->super.Detach == NULL) {
140 HDF_LOGE("failed to del device, invalid device");
141 return HDF_ERR_INVALID_OBJECT;
142 }
143
144 if (device->super.Detach(&device->super, devNode) != HDF_SUCCESS) {
145 HDF_LOGE("failed to detach device");
146 return HDF_FAILURE;
147 }
148 HdfDeviceNodeFreeInstance(devNode);
149
150 if (DListIsEmpty(&device->devNodes)) {
151 DevHostServiceFreeDevice(hostService, device);
152 }
153 HDF_LOGD("%{public}s add device success", __func__);
154 return HDF_SUCCESS;
155 }
156
DevHostServiceStartService(struct IDevHostService * service)157 static int DevHostServiceStartService(struct IDevHostService *service)
158 {
159 struct DevHostService *hostService = (struct DevHostService*)service;
160 if (hostService == NULL) {
161 HDF_LOGE("failed to start device service, hostService is null");
162 return HDF_FAILURE;
163 }
164 return DevmgrServiceClntAttachDeviceHost(hostService->hostId, service);
165 }
166
ApplyDevicesPowerState(struct HdfDevice * device,uint32_t state)167 static int ApplyDevicesPowerState(struct HdfDevice *device, uint32_t state)
168 {
169 struct HdfDeviceNode *deviceNode = NULL;
170 int ret;
171
172 /* The power management strategy is to ignore devices that fail to
173 operate and avoid more devices that fail to sleep or wake up */
174 if (IsPowerWakeState(state)) {
175 DLIST_FOR_EACH_ENTRY(deviceNode, &device->devNodes, struct HdfDeviceNode, entry) {
176 if (deviceNode->powerToken != NULL) {
177 ret = PowerStateChange(deviceNode->powerToken, state);
178 if (ret != HDF_SUCCESS) {
179 HDF_LOGE("device %{public}s failed to resume(%{public}u)",
180 deviceNode->driver->entry->moduleName, state);
181 }
182 }
183 }
184 } else {
185 DLIST_FOR_EACH_ENTRY_REVERSE(deviceNode, &device->devNodes, struct HdfDeviceNode, entry) {
186 if (deviceNode->powerToken != NULL) {
187 ret = PowerStateChange(deviceNode->powerToken, state);
188 if (ret != HDF_SUCCESS) {
189 HDF_LOGE("device %{public}s failed to suspend(%{public}u)",
190 deviceNode->driver->entry->moduleName, state);
191 }
192 }
193 }
194 }
195
196 return HDF_SUCCESS;
197 }
198
DevHostServicePmNotify(struct IDevHostService * service,uint32_t state)199 static int DevHostServicePmNotify(struct IDevHostService *service, uint32_t state)
200 {
201 struct HdfDevice *device = NULL;
202 int ret = HDF_SUCCESS;
203 struct DevHostService *hostService = CONTAINER_OF(service, struct DevHostService, super);
204 if (hostService == NULL) {
205 HDF_LOGE("failed to start device service, hostService is null");
206 return HDF_FAILURE;
207 }
208
209 HDF_LOGD("host(%{public}s) set power state=%{public}u", hostService->hostName, state);
210 if (IsPowerWakeState(state)) {
211 DLIST_FOR_EACH_ENTRY_REVERSE(device, &hostService->devices, struct HdfDevice, node) {
212 if (ApplyDevicesPowerState(device, state) != HDF_SUCCESS) {
213 ret = HDF_FAILURE;
214 }
215 }
216 } else {
217 DLIST_FOR_EACH_ENTRY(device, &hostService->devices, struct HdfDevice, node) {
218 if (ApplyDevicesPowerState(device, state) != HDF_SUCCESS) {
219 ret = HDF_FAILURE;
220 }
221 }
222 }
223
224 return ret;
225 }
226
DevHostServiceConstruct(struct DevHostService * service)227 void DevHostServiceConstruct(struct DevHostService *service)
228 {
229 if (service == NULL) {
230 return;
231 }
232 struct IDevHostService *hostServiceIf = &service->super;
233 hostServiceIf->AddDevice = DevHostServiceAddDevice;
234 hostServiceIf->DelDevice = DevHostServiceDelDevice;
235 hostServiceIf->StartService = DevHostServiceStartService;
236 hostServiceIf->PmNotify = DevHostServicePmNotify;
237 DListHeadInit(&service->devices);
238 HdfServiceObserverConstruct(&service->observer);
239 }
240
DevHostServiceDestruct(struct DevHostService * service)241 void DevHostServiceDestruct(struct DevHostService *service)
242 {
243 struct HdfDevice *device = NULL;
244 struct HdfDevice *tmp = NULL;
245 if (service == NULL) {
246 return;
247 }
248
249 DLIST_FOR_EACH_ENTRY_SAFE(device, tmp, &service->devices, struct HdfDevice, node) {
250 HdfDeviceFreeInstance(device);
251 }
252 HdfServiceObserverDestruct(&service->observer);
253 }
254
DevHostServiceCreate(void)255 struct HdfObject *DevHostServiceCreate(void)
256 {
257 struct DevHostService *devHostService = (struct DevHostService *)OsalMemCalloc(sizeof(struct DevHostService));
258 if (devHostService != NULL) {
259 DevHostServiceConstruct(devHostService);
260 }
261 return (struct HdfObject *)devHostService;
262 }
263
DevHostServiceRelease(struct HdfObject * object)264 void DevHostServiceRelease(struct HdfObject *object)
265 {
266 struct DevHostService *devHostService = (struct DevHostService *)object;
267 if (devHostService != NULL) {
268 DevHostServiceDestruct(devHostService);
269 OsalMemFree(devHostService);
270 }
271 }
272
DevHostServiceNewInstance(uint16_t hostId,const char * hostName)273 struct IDevHostService *DevHostServiceNewInstance(uint16_t hostId, const char *hostName)
274 {
275 struct DevHostService *hostService =
276 (struct DevHostService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVHOST_SERVICE);
277 if (hostService != NULL && hostName != NULL) {
278 hostService->hostId = hostId;
279 hostService->hostName = hostName;
280 }
281 return (struct IDevHostService *)hostService;
282 }
283
DevHostServiceFreeInstance(struct IDevHostService * service)284 void DevHostServiceFreeInstance(struct IDevHostService *service)
285 {
286 if (service != NULL) {
287 HdfObjectManagerFreeObject(&service->object);
288 }
289 }
290