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