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