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 PLAT_LOGD("PlatformDeviceSetName: tmpName:%s, realLen:%zu", tmpName, realLen);
88 ret = strncpy_s(realName, realLen + 1, tmpName, realLen);
89 if (ret != EOK) {
90 OsalMemFree(realName);
91 PLAT_LOGE("PlatformDeviceSetName: copy name failed:%d", ret);
92 return HDF_ERR_IO;
93 }
94
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
PlatformDeviceBind(struct PlatformDevice * device,struct HdfDeviceObject * hdfDevice)274 int32_t PlatformDeviceBind(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->service = device->service;
287 hdfDevice->priv = device;
288 return HDF_SUCCESS;
289 }
290
PlatformDeviceUnbind(struct PlatformDevice * device,struct HdfDeviceObject * hdfDev)291 void PlatformDeviceUnbind(struct PlatformDevice *device, struct HdfDeviceObject *hdfDev)
292 {
293 if (device == NULL) {
294 return;
295 }
296 if (device->hdfDev == NULL) {
297 return;
298 }
299 if (device->hdfDev != hdfDev) {
300 PLAT_LOGW("PlatformDeviceUnbind: hdf device not match!");
301 return;
302 }
303
304 device->hdfDev->service = NULL;
305 device->hdfDev->priv = NULL;
306 device->hdfDev = NULL;
307 }
308
PlatformDeviceFromHdfDev(struct HdfDeviceObject * hdfDev)309 struct PlatformDevice *PlatformDeviceFromHdfDev(struct HdfDeviceObject *hdfDev)
310 {
311 if (hdfDev == NULL || hdfDev->priv == NULL) {
312 PLAT_LOGE("PlatformDeviceFromHdfDev: hdf device or priv null");
313 return NULL;
314 }
315
316 return (struct PlatformDevice *)hdfDev->priv;
317 }
318
PlatformDevicePostEvent(struct PlatformDevice * device,uint32_t events)319 int32_t PlatformDevicePostEvent(struct PlatformDevice *device, uint32_t events)
320 {
321 if (device == NULL) {
322 return HDF_ERR_INVALID_OBJECT;
323 }
324 return PlatformEventPost(&device->event, events);
325 }
326
PlatformDeviceWaitEvent(struct PlatformDevice * device,uint32_t mask,uint32_t tms,uint32_t * events)327 int32_t PlatformDeviceWaitEvent(struct PlatformDevice *device, uint32_t mask, uint32_t tms, uint32_t *events)
328 {
329 int32_t ret;
330 uint32_t eventsRead;
331
332 if (device == NULL) {
333 return HDF_ERR_INVALID_OBJECT;
334 }
335 ret = PlatformEventWait(&device->event, mask, PLAT_EVENT_MODE_CLEAR, tms, &eventsRead);
336 if (ret != HDF_SUCCESS) {
337 return ret;
338 }
339
340 if (eventsRead == 0) {
341 return HDF_FAILURE;
342 }
343 if (events != NULL) {
344 *events = eventsRead;
345 }
346 return HDF_SUCCESS;
347 }
348
PlatformDeviceListenEvent(struct PlatformDevice * device,struct PlatformEventListener * listener)349 int32_t PlatformDeviceListenEvent(struct PlatformDevice *device, struct PlatformEventListener *listener)
350 {
351 if (device == NULL) {
352 return HDF_ERR_INVALID_OBJECT;
353 }
354 if (listener == NULL) {
355 return HDF_ERR_INVALID_PARAM;
356 }
357 return PlatformEventListen(&device->event, listener);
358 }
359
PlatformDeviceUnListenEvent(struct PlatformDevice * device,struct PlatformEventListener * listener)360 void PlatformDeviceUnListenEvent(struct PlatformDevice *device, struct PlatformEventListener *listener)
361 {
362 if (device != NULL && listener != NULL) {
363 PlatformEventUnlisten(&device->event, listener);
364 }
365 }
366