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