• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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