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