1 /*
2 * Copyright (c) 2020-2023 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 "platform_device.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "platform_core.h"
13 #include "securec.h"
14 #include "stdarg.h"
15
16 #define PLATFORM_DEV_NAME_DEFAULT "platform_device"
17
PlatformDeviceOnFirstGet(struct HdfSRef * sref)18 static void PlatformDeviceOnFirstGet(struct HdfSRef *sref)
19 {
20 (void)sref;
21 }
22
PlatformDeviceOnLastPut(struct HdfSRef * sref)23 static void PlatformDeviceOnLastPut(struct HdfSRef *sref)
24 {
25 struct PlatformDevice *device = NULL;
26 int32_t ret;
27
28 if (sref == NULL) {
29 PLAT_LOGE("PlatformDeviceOnLastPut: sref is null!");
30 return;
31 }
32
33 device = CONTAINER_OF(sref, struct PlatformDevice, ref);
34 if (device == NULL) {
35 PLAT_LOGE("PlatformDeviceOnLastPut: get device is null!");
36 return;
37 }
38
39 ret = PlatformDevicePostEvent(device, PLAT_EVENT_DEVICE_DEAD);
40 if (ret != HDF_SUCCESS) {
41 PLAT_LOGE("PlatformDeviceOnLastPut: post event fail, ret: %d!", ret);
42 return;
43 }
44 PLAT_LOGI("PlatformDeviceOnLastPut: device:%s(%d) life cycle end", device->name, device->number);
45 }
46
47 struct IHdfSRefListener g_platObjListener = {
48 .OnFirstAcquire = PlatformDeviceOnFirstGet,
49 .OnLastRelease = PlatformDeviceOnLastPut,
50 };
51
52 #define PLATFORM_DEV_NAME_LEN 64
PlatformDeviceSetName(struct PlatformDevice * device,const char * fmt,...)53 int32_t PlatformDeviceSetName(struct PlatformDevice *device, const char *fmt, ...)
54 {
55 int ret;
56 char tmpName[PLATFORM_DEV_NAME_LEN + 1] = {0};
57 size_t realLen;
58 va_list vargs;
59 char *realName = NULL;
60
61 if (device == NULL) {
62 PLAT_LOGE("PlatformDeviceSetName: device is null!");
63 return HDF_ERR_INVALID_OBJECT;
64 }
65
66 if (fmt == NULL) {
67 PLAT_LOGE("PlatformDeviceSetName: fmt is null!");
68 return HDF_ERR_INVALID_PARAM;
69 }
70
71 va_start(vargs, fmt);
72 ret = vsnprintf_s(tmpName, PLATFORM_DEV_NAME_LEN, PLATFORM_DEV_NAME_LEN, fmt, vargs);
73 va_end(vargs);
74 if (ret <= 0) {
75 PLAT_LOGE("PlatformDeviceSetName: fail to format device name, ret: %d!", ret);
76 return HDF_PLT_ERR_OS_API;
77 }
78
79 realLen = strlen(tmpName);
80 if (realLen == 0 || realLen > PLATFORM_DEV_NAME_LEN) {
81 PLAT_LOGE("PlatformDeviceSetName: invalid name len:%zu!", realLen);
82 return HDF_ERR_INVALID_PARAM;
83 }
84 realName = OsalMemCalloc(realLen + 1);
85 if (realName == NULL) {
86 PLAT_LOGE("PlatformDeviceSetName: memcalloc name mem fail!");
87 return HDF_ERR_MALLOC_FAIL;
88 }
89
90 ret = strncpy_s(realName, realLen + 1, tmpName, realLen);
91 if (ret != EOK) {
92 OsalMemFree(realName);
93 PLAT_LOGE("PlatformDeviceSetName: copy name(%s) fail, ret: %d!", tmpName, ret);
94 return HDF_ERR_IO;
95 }
96
97 PLAT_LOGD("PlatformDeviceSetName: realName:%s, realLen:%zu!", realName, realLen);
98 device->name = (const char *)realName;
99 return HDF_SUCCESS;
100 }
101
PlatformDeviceClearName(struct PlatformDevice * device)102 void PlatformDeviceClearName(struct PlatformDevice *device)
103 {
104 if (device != NULL && device->name != NULL) {
105 OsalMemFree((char *)device->name);
106 device->name = NULL;
107 }
108 }
109
PlatformDeviceInit(struct PlatformDevice * device)110 int32_t PlatformDeviceInit(struct PlatformDevice *device)
111 {
112 int32_t ret;
113
114 if (device == NULL) {
115 PLAT_LOGE("PlatformDeviceInit: device is null!");
116 return HDF_ERR_INVALID_OBJECT;
117 }
118
119 if ((ret = OsalSpinInit(&device->spin)) != HDF_SUCCESS) {
120 PLAT_LOGE("PlatformDeviceInit: spin init fail!");
121 return ret;
122 }
123 if ((ret = OsalSemInit(&device->released, 0)) != HDF_SUCCESS) {
124 (void)OsalSpinDestroy(&device->spin);
125 PLAT_LOGE("PlatformDeviceInit: sem init fail!");
126 return ret;
127 }
128 if ((ret = PlatformEventInit(&device->event)) != HDF_SUCCESS) {
129 (void)OsalSemDestroy(&device->released);
130 (void)OsalSpinDestroy(&device->spin);
131 PLAT_LOGE("PlatformDeviceInit: event init fail!");
132 return ret;
133 }
134 DListHeadInit(&device->node);
135 HdfSRefConstruct(&device->ref, &g_platObjListener);
136
137 return HDF_SUCCESS;
138 }
139
PlatformDeviceUninit(struct PlatformDevice * device)140 void PlatformDeviceUninit(struct PlatformDevice *device)
141 {
142 if (device == NULL) {
143 PLAT_LOGW("PlatformDeviceUninit: device is null!");
144 return;
145 }
146
147 (void)PlatformEventUninit(&device->event);
148 (void)OsalSemDestroy(&device->released);
149 (void)OsalSpinDestroy(&device->spin);
150 }
151
PlatformDeviceGet(struct PlatformDevice * device)152 int32_t PlatformDeviceGet(struct PlatformDevice *device)
153 {
154 if (device == NULL) {
155 PLAT_LOGE("PlatformDeviceGet: device is null!");
156 return HDF_ERR_INVALID_OBJECT;
157 }
158
159 HdfSRefAcquire(&device->ref);
160 return HDF_SUCCESS;
161 }
162
PlatformDevicePut(struct PlatformDevice * device)163 void PlatformDevicePut(struct PlatformDevice *device)
164 {
165 if (device != NULL) {
166 HdfSRefRelease(&device->ref);
167 }
168 }
169
PlatformDeviceRefCount(struct PlatformDevice * device)170 int32_t PlatformDeviceRefCount(struct PlatformDevice *device)
171 {
172 if (device != NULL) {
173 return HdfSRefCount(&device->ref);
174 }
175 return HDF_ERR_INVALID_OBJECT;
176 }
177
PlatformDeviceAdd(struct PlatformDevice * device)178 int32_t PlatformDeviceAdd(struct PlatformDevice *device)
179 {
180 int32_t ret;
181 struct PlatformManager *manager = NULL;
182
183 if (device == NULL) {
184 PLAT_LOGE("PlatformDeviceAdd: device is null!");
185 return HDF_ERR_INVALID_OBJECT;
186 }
187
188 manager = device->manager;
189 if (manager == NULL) {
190 manager = PlatformManagerGet(PLATFORM_MODULE_DEFAULT);
191 if (manager == NULL) {
192 PLAT_LOGE("PlatformDeviceAdd: get default manager fail!");
193 return HDF_PLT_ERR_INNER;
194 }
195 }
196
197 if ((ret = PlatformDeviceInit(device)) != HDF_SUCCESS) {
198 return ret;
199 }
200
201 ret = PlatformManagerAddDevice(manager, device);
202 if (ret == HDF_SUCCESS) {
203 device->manager = manager;
204 PLAT_LOGD("PlatformDeviceAdd: add dev:%s(%d) success", device->name, device->number);
205 } else {
206 PLAT_LOGE("PlatformDeviceAdd: add %s(%d) fail, ret: %d!", device->name, device->number, ret);
207 PlatformDeviceUninit(device);
208 }
209 return ret;
210 }
211
PlatformDeviceDel(struct PlatformDevice * device)212 void PlatformDeviceDel(struct PlatformDevice *device)
213 {
214 int32_t ret;
215 struct PlatformManager *manager = NULL;
216
217 if (device == NULL) {
218 PLAT_LOGE("PlatformDeviceDel: device is null!");
219 return;
220 }
221
222 manager = device->manager;
223 if (manager == NULL) {
224 manager = PlatformManagerGet(PLATFORM_MODULE_DEFAULT);
225 if (manager == NULL) {
226 PLAT_LOGE("PlatformDeviceDel: get default manager fail!");
227 return;
228 }
229 }
230 ret = PlatformManagerDelDevice(manager, device);
231 if (ret != HDF_SUCCESS) {
232 PLAT_LOGW("PlatformDeviceDel: fail to remove device:%s from manager:%s!",
233 device->name, manager->device.name);
234 return; // it's dagerous to continue ...
235 }
236
237 /* make sure no reference anymore before exit. */
238 ret = PlatformDeviceWaitEvent(device, PLAT_EVENT_DEVICE_DEAD, HDF_WAIT_FOREVER, NULL);
239 if (ret == HDF_SUCCESS) {
240 PLAT_LOGD("PlatformDeviceDel: remove dev:%s(%d) success", device->name, device->number);
241 } else {
242 PLAT_LOGE("PlatformDeviceDel: wait %s(%d) dead fail, ret: %d!", device->name, device->number, ret);
243 }
244 PlatformDeviceUninit(device);
245 }
246
PlatformDeviceCreateService(struct PlatformDevice * device,int32_t (* dispatch)(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply))247 int32_t PlatformDeviceCreateService(struct PlatformDevice *device,
248 int32_t (*dispatch)(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply))
249 {
250 if (device == NULL) {
251 PLAT_LOGE("PlatformDeviceCreateService: device is null!");
252 return HDF_ERR_INVALID_OBJECT;
253 }
254
255 if (device->service != NULL) {
256 PLAT_LOGE("PlatformDeviceCreateService: service already creatted!");
257 return HDF_FAILURE;
258 }
259
260 device->service = (struct IDeviceIoService *)OsalMemCalloc(sizeof(*(device->service)));
261 if (device->service == NULL) {
262 PLAT_LOGE("PlatformDeviceCreateService: memcalloc service fail!");
263 return HDF_ERR_MALLOC_FAIL;
264 }
265
266 device->service->Dispatch = dispatch;
267 return HDF_SUCCESS;
268 }
269
PlatformDeviceDestroyService(struct PlatformDevice * device)270 void PlatformDeviceDestroyService(struct PlatformDevice *device)
271 {
272 if (device == NULL) {
273 PLAT_LOGE("PlatformDeviceDestroyService: device is null!");
274 return;
275 }
276
277 if (device->service == NULL) {
278 PLAT_LOGE("PlatformDeviceDestroyService: service is null!");
279 return;
280 }
281
282 OsalMemFree(device->service);
283 device->service = NULL;
284 }
285
PlatformDeviceSetHdfDev(struct PlatformDevice * device,struct HdfDeviceObject * hdfDevice)286 int32_t PlatformDeviceSetHdfDev(struct PlatformDevice *device, struct HdfDeviceObject *hdfDevice)
287 {
288 if (device == NULL || hdfDevice == NULL) {
289 PLAT_LOGE("PlatformDeviceSetHdfDev: device or hdfDevice is null!");
290 return HDF_ERR_INVALID_OBJECT;
291 }
292
293 if (device->hdfDev != NULL) {
294 PLAT_LOGE("PlatformDeviceSetHdfDev: already bind a hdf device!");
295 return HDF_FAILURE;
296 }
297
298 device->hdfDev = hdfDevice;
299 hdfDevice->priv = device;
300 return HDF_SUCCESS;
301 }
302
PlatformDeviceBind(struct PlatformDevice * device,struct HdfDeviceObject * hdfDevice)303 int32_t PlatformDeviceBind(struct PlatformDevice *device, struct HdfDeviceObject *hdfDevice)
304 {
305 int32_t ret;
306
307 ret = PlatformDeviceSetHdfDev(device, hdfDevice);
308 if (ret == HDF_SUCCESS) {
309 hdfDevice->service = device->service;
310 }
311 return ret;
312 }
313
PlatformDeviceUnbind(struct PlatformDevice * device,const struct HdfDeviceObject * hdfDev)314 void PlatformDeviceUnbind(struct PlatformDevice *device, const struct HdfDeviceObject *hdfDev)
315 {
316 if (device == NULL) {
317 PLAT_LOGE("PlatformDeviceUnbind: device is null!");
318 return;
319 }
320 if (device->hdfDev == NULL) {
321 PLAT_LOGE("PlatformDeviceUnbind: hdfDev is null!");
322 return;
323 }
324 if (device->hdfDev != hdfDev) {
325 PLAT_LOGW("PlatformDeviceUnbind: hdf device not match!");
326 return;
327 }
328
329 device->hdfDev->service = NULL;
330 device->hdfDev->priv = NULL;
331 device->hdfDev = NULL;
332 }
333
PlatformDeviceFromHdfDev(const struct HdfDeviceObject * hdfDev)334 struct PlatformDevice *PlatformDeviceFromHdfDev(const struct HdfDeviceObject *hdfDev)
335 {
336 if (hdfDev == NULL || hdfDev->priv == NULL) {
337 PLAT_LOGE("PlatformDeviceFromHdfDev: hdf device or priv is null!");
338 return NULL;
339 }
340
341 return (struct PlatformDevice *)hdfDev->priv;
342 }
343
PlatformDevicePostEvent(struct PlatformDevice * device,uint32_t events)344 int32_t PlatformDevicePostEvent(struct PlatformDevice *device, uint32_t events)
345 {
346 if (device == NULL) {
347 PLAT_LOGE("PlatformDevicePostEvent: device is null!");
348 return HDF_ERR_INVALID_OBJECT;
349 }
350 return PlatformEventPost(&device->event, events);
351 }
352
PlatformDeviceWaitEvent(struct PlatformDevice * device,uint32_t mask,uint32_t tms,uint32_t * events)353 int32_t PlatformDeviceWaitEvent(struct PlatformDevice *device, uint32_t mask, uint32_t tms, uint32_t *events)
354 {
355 int32_t ret;
356 uint32_t eventsRead;
357
358 if (device == NULL) {
359 PLAT_LOGE("PlatformDeviceWaitEvent: device is null!");
360 return HDF_ERR_INVALID_OBJECT;
361 }
362 ret = PlatformEventWait(&device->event, mask, PLAT_EVENT_MODE_CLEAR, tms, &eventsRead);
363 if (ret != HDF_SUCCESS) {
364 PLAT_LOGE("PlatformDeviceWaitEvent: event wait fail!");
365 return ret;
366 }
367
368 if (eventsRead == 0) {
369 PLAT_LOGE("PlatformDeviceWaitEvent: no event read!");
370 return HDF_FAILURE;
371 }
372 if (events != NULL) {
373 *events = eventsRead;
374 }
375 return HDF_SUCCESS;
376 }
377
PlatformDeviceListenEvent(struct PlatformDevice * device,struct PlatformEventListener * listener)378 int32_t PlatformDeviceListenEvent(struct PlatformDevice *device, struct PlatformEventListener *listener)
379 {
380 if (device == NULL) {
381 PLAT_LOGE("PlatformDeviceListenEvent: device is null!");
382 return HDF_ERR_INVALID_OBJECT;
383 }
384 if (listener == NULL) {
385 PLAT_LOGE("PlatformDeviceListenEvent: listener is null!");
386 return HDF_ERR_INVALID_PARAM;
387 }
388 return PlatformEventListen(&device->event, listener);
389 }
390
PlatformDeviceUnListenEvent(struct PlatformDevice * device,struct PlatformEventListener * listener)391 void PlatformDeviceUnListenEvent(struct PlatformDevice *device, struct PlatformEventListener *listener)
392 {
393 if (device != NULL && listener != NULL) {
394 PlatformEventUnlisten(&device->event, listener);
395 }
396 }
397
PlatformDeviceGetDrs(const struct PlatformDevice * device)398 const struct DeviceResourceNode *PlatformDeviceGetDrs(const struct PlatformDevice *device)
399 {
400 #ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO
401 (void)device;
402 return NULL;
403 #else
404 if (device != NULL && device->hdfDev != NULL) {
405 return device->hdfDev->property;
406 }
407 return NULL;
408 #endif
409 }
410