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