1 /*
2 * Copyright (c) 2022 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 "timer_core.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "osal_time.h"
13 #include "securec.h"
14
15 #define HDF_LOG_TAG timer_core
16
17 struct TimerManager {
18 struct IDeviceIoService service;
19 struct HdfDeviceObject *device;
20 struct DListHead timerListHead;
21 struct OsalMutex lock;
22 };
23
24 static struct TimerManager *g_timerManager = NULL;
25 #define TIMER_HANDLE_SHIFT ((uintptr_t)(-1) << 16)
26
TimerCntrlOpen(const uint32_t number)27 struct TimerCntrl *TimerCntrlOpen(const uint32_t number)
28 {
29 struct TimerCntrl *pos = NULL;
30 struct TimerManager *manager = g_timerManager;
31 CHECK_NULL_PTR_RETURN_VALUE(manager, NULL);
32
33 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
34 HDF_LOGE("%s: OsalMutexLock failed", __func__);
35 return NULL;
36 }
37
38 DLIST_FOR_EACH_ENTRY(pos, &manager->timerListHead, struct TimerCntrl, node) {
39 if (number == pos->info.number) {
40 (void)OsalMutexUnlock(&manager->lock);
41 return pos;
42 }
43 }
44
45 (void)OsalMutexUnlock(&manager->lock);
46 HDF_LOGE("%s: open %u failed", __func__, number);
47 return NULL;
48 }
49
TimerCntrlClose(struct TimerCntrl * cntrl)50 int32_t TimerCntrlClose(struct TimerCntrl *cntrl)
51 {
52 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
53 if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
54 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
55 return HDF_ERR_DEVICE_BUSY;
56 }
57 if ((cntrl->ops->Close != NULL) && (cntrl->ops->Close(cntrl) != HDF_SUCCESS)) {
58 HDF_LOGE("%s: close %u failed", __func__, cntrl->info.number);
59 (void)OsalMutexUnlock(&cntrl->lock);
60 return HDF_FAILURE;
61 }
62 (void)OsalMutexUnlock(&cntrl->lock);
63 return HDF_SUCCESS;
64 }
65
TimerCntrlSet(struct TimerCntrl * cntrl,uint32_t useconds,TimerHandleCb cb)66 int32_t TimerCntrlSet(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb)
67 {
68 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
69 CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT);
70 if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
71 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
72 return HDF_ERR_DEVICE_BUSY;
73 }
74 if ((cntrl->ops->Set != NULL) && (cntrl->ops->Set(cntrl, useconds, cb) != HDF_SUCCESS)) {
75 HDF_LOGE("%s: set %u failed", __func__, cntrl->info.number);
76 (void)OsalMutexUnlock(&cntrl->lock);
77 return HDF_FAILURE;
78 }
79
80 (void)OsalMutexUnlock(&cntrl->lock);
81 return HDF_SUCCESS;
82 }
83
TimerCntrlSetOnce(struct TimerCntrl * cntrl,uint32_t useconds,TimerHandleCb cb)84 int32_t TimerCntrlSetOnce(struct TimerCntrl *cntrl, uint32_t useconds, TimerHandleCb cb)
85 {
86 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
87 CHECK_NULL_PTR_RETURN_VALUE(cb, HDF_ERR_INVALID_OBJECT);
88
89 if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
90 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
91 return HDF_ERR_DEVICE_BUSY;
92 }
93 if ((cntrl->ops->SetOnce != NULL) && (cntrl->ops->SetOnce(cntrl, useconds, cb) != HDF_SUCCESS)) {
94 HDF_LOGE("%s: setOnce %u failed", __func__, cntrl->info.number);
95 (void)OsalMutexUnlock(&cntrl->lock);
96 return HDF_FAILURE;
97 }
98
99 (void)OsalMutexUnlock(&cntrl->lock);
100 return HDF_SUCCESS;
101 }
102
TimerCntrlGet(struct TimerCntrl * cntrl,uint32_t * useconds,bool * isPeriod)103 int32_t TimerCntrlGet(struct TimerCntrl *cntrl, uint32_t *useconds, bool *isPeriod)
104 {
105 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
106 CHECK_NULL_PTR_RETURN_VALUE(useconds, HDF_ERR_INVALID_OBJECT);
107 CHECK_NULL_PTR_RETURN_VALUE(isPeriod, HDF_ERR_INVALID_OBJECT);
108
109 if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
110 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
111 return HDF_ERR_DEVICE_BUSY;
112 }
113 *useconds = cntrl->info.useconds;
114 *isPeriod = cntrl->info.isPeriod;
115 (void)OsalMutexUnlock(&cntrl->lock);
116 return HDF_SUCCESS;
117 }
118
TimerCntrlStart(struct TimerCntrl * cntrl)119 int32_t TimerCntrlStart(struct TimerCntrl *cntrl)
120 {
121 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
122
123 if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
124 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
125 return HDF_ERR_DEVICE_BUSY;
126 }
127 if ((cntrl->ops->Start != NULL) && (cntrl->ops->Start(cntrl) != HDF_SUCCESS)) {
128 HDF_LOGE("%s: start %u failed", __func__, cntrl->info.number);
129 (void)OsalMutexUnlock(&cntrl->lock);
130 return HDF_FAILURE;
131 }
132 (void)OsalMutexUnlock(&cntrl->lock);
133 return HDF_SUCCESS;
134 }
135
TimerCntrlStop(struct TimerCntrl * cntrl)136 int32_t TimerCntrlStop(struct TimerCntrl *cntrl)
137 {
138 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_OBJECT);
139
140 if (OsalMutexLock(&cntrl->lock) != HDF_SUCCESS) {
141 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
142 return HDF_ERR_DEVICE_BUSY;
143 }
144 if ((cntrl->ops->Stop != NULL) && (cntrl->ops->Stop(cntrl) != HDF_SUCCESS)) {
145 HDF_LOGE("%s: stop %u failed", __func__, cntrl->info.number);
146 (void)OsalMutexUnlock(&cntrl->lock);
147 return HDF_FAILURE;
148 }
149
150 (void)OsalMutexUnlock(&cntrl->lock);
151 return HDF_SUCCESS;
152 }
153
TimerIoOpen(struct HdfSBuf * data,struct HdfSBuf * reply)154 static int32_t TimerIoOpen(struct HdfSBuf *data, struct HdfSBuf *reply)
155 {
156 int16_t number;
157 uint32_t handle;
158
159 if ((data == NULL) || (reply == NULL)) {
160 HDF_LOGE("%s: param invalid", __func__);
161 return HDF_ERR_INVALID_PARAM;
162 }
163 if (!HdfSbufReadUint16(data, (uint16_t *)&number)) {
164 HDF_LOGE("%s: HdfSbufReadUint16 failed", __func__);
165 return HDF_ERR_IO;
166 }
167
168 if (number < 0) {
169 HDF_LOGE("%s: info read failed", __func__);
170 return HDF_ERR_INVALID_PARAM;
171 }
172
173 if (TimerCntrlOpen(number) == NULL) {
174 HDF_LOGE("%s: TimerCntrlOpen %d failed", __func__, number);
175 return HDF_FAILURE;
176 }
177
178 handle = (uint32_t)(number + TIMER_HANDLE_SHIFT);
179 if (!HdfSbufWriteUint32(reply, handle)) {
180 HDF_LOGE("%s: HdfSbufWriteUint32 failed", __func__);
181 return HDF_ERR_IO;
182 }
183 return HDF_SUCCESS;
184 }
185
TimerIoClose(struct HdfSBuf * data,struct HdfSBuf * reply)186 static int32_t TimerIoClose(struct HdfSBuf *data, struct HdfSBuf *reply)
187 {
188 uint32_t handle;
189 int16_t number;
190 if (data == NULL) {
191 HDF_LOGE("%s: param invalid", __func__);
192 return HDF_ERR_INVALID_PARAM;
193 }
194
195 if (!HdfSbufReadUint32(data, &handle)) {
196 HDF_LOGE("%s: HdfSbufReadUint32 failed", __func__);
197 return HDF_ERR_IO;
198 }
199
200 number = (int16_t)(handle - TIMER_HANDLE_SHIFT);
201 if (number < 0) {
202 HDF_LOGE("%s: number[%d] invalid", __func__, number);
203 return HDF_ERR_INVALID_PARAM;
204 }
205 return TimerCntrlClose(TimerCntrlOpen(number));
206 }
207
TimerIoStart(struct HdfSBuf * data,struct HdfSBuf * reply)208 static int32_t TimerIoStart(struct HdfSBuf *data, struct HdfSBuf *reply)
209 {
210 uint32_t handle;
211 int16_t number;
212 if (data == NULL) {
213 HDF_LOGE("%s: param invalid", __func__);
214 return HDF_ERR_INVALID_PARAM;
215 }
216 if (!HdfSbufReadUint32(data, &handle)) {
217 HDF_LOGE("%s: HdfSbufReadUint32 failed", __func__);
218 return HDF_ERR_IO;
219 }
220
221 number = (int16_t)(handle - TIMER_HANDLE_SHIFT);
222 if (number < 0) {
223 HDF_LOGE("%s: number[%d] invalid", __func__, number);
224 return HDF_ERR_INVALID_PARAM;
225 }
226 return TimerCntrlStart(TimerCntrlOpen(number));
227 }
228
TimerIoStop(struct HdfSBuf * data,struct HdfSBuf * reply)229 static int32_t TimerIoStop(struct HdfSBuf *data, struct HdfSBuf *reply)
230 {
231 uint32_t handle;
232 int16_t number;
233 if (data == NULL) {
234 HDF_LOGE("%s: param invalid", __func__);
235 return HDF_ERR_INVALID_PARAM;
236 }
237 if (!HdfSbufReadUint32(data, &handle)) {
238 HDF_LOGE("%s: HdfSbufReadUint32 failed", __func__);
239 return HDF_ERR_IO;
240 }
241
242 number = (int16_t)(handle - TIMER_HANDLE_SHIFT);
243 if (number < 0) {
244 HDF_LOGE("%s: number[%d] invalid", __func__, number);
245 return HDF_ERR_INVALID_PARAM;
246 }
247 return TimerCntrlStop(TimerCntrlOpen(number));
248 }
249
TimerIoCb()250 static int32_t TimerIoCb()
251 {
252 return HDF_SUCCESS;
253 }
254
TimerIoSet(struct HdfSBuf * data,struct HdfSBuf * reply)255 static int32_t TimerIoSet(struct HdfSBuf *data, struct HdfSBuf *reply)
256 {
257 uint32_t len;
258 uint32_t handle;
259 int16_t number;
260 struct TimerConfig *cfg = NULL;
261 if (data == NULL) {
262 HDF_LOGE("%s: param invalid", __func__);
263 return HDF_ERR_INVALID_PARAM;
264 }
265 if (!HdfSbufReadUint32(data, &handle)) {
266 HDF_LOGE("%s: read handle failed!", __func__);
267 return HDF_ERR_IO;
268 }
269
270 if (!HdfSbufReadBuffer(data, (const void **)&cfg, &len) || cfg == NULL) {
271 HDF_LOGE("%s: read buffer failed!", __func__);
272 return HDF_ERR_IO;
273 }
274
275 number = (int16_t)(handle - TIMER_HANDLE_SHIFT);
276 if (number < 0) {
277 HDF_LOGE("%s: number[%d] invalid", __func__, number);
278 return HDF_ERR_INVALID_PARAM;
279 }
280 return TimerCntrlSet(TimerCntrlOpen(number), cfg->useconds, TimerIoCb);
281 }
282
TimerIoSetOnce(struct HdfSBuf * data,struct HdfSBuf * reply)283 static int32_t TimerIoSetOnce(struct HdfSBuf *data, struct HdfSBuf *reply)
284 {
285 uint32_t len;
286 uint32_t handle;
287 int16_t number;
288 struct TimerConfig *cfg = NULL;
289 if (data == NULL) {
290 HDF_LOGE("%s: param invalid", __func__);
291 return HDF_ERR_INVALID_PARAM;
292 }
293 if (!HdfSbufReadUint32(data, &handle)) {
294 HDF_LOGE("%s: read handle failed!", __func__);
295 return HDF_ERR_IO;
296 }
297
298 if (!HdfSbufReadBuffer(data, (const void **)&cfg, &len) || cfg == NULL) {
299 HDF_LOGE("%s: read buffer failed!", __func__);
300 return HDF_ERR_IO;
301 }
302
303 number = (int16_t)(handle - TIMER_HANDLE_SHIFT);
304 if (number < 0) {
305 HDF_LOGE("%s: number[%d] invalid", __func__, number);
306 return HDF_ERR_INVALID_PARAM;
307 }
308 return TimerCntrlSetOnce(TimerCntrlOpen(number), cfg->useconds, TimerIoCb);
309 }
310
TimerIoGet(struct HdfSBuf * data,struct HdfSBuf * reply)311 static int32_t TimerIoGet(struct HdfSBuf *data, struct HdfSBuf *reply)
312 {
313 int32_t ret = HDF_SUCCESS;
314 struct TimerConfig cfg;
315 uint32_t handle;
316 int16_t number;
317 if ((data == NULL) || (reply == NULL)) {
318 HDF_LOGE("%s: param null", __func__);
319 return HDF_ERR_INVALID_PARAM;
320 }
321
322 if (!HdfSbufReadUint32(data, &handle)) {
323 HDF_LOGE("%s: HdfSbufReadUint32 failed", __func__);
324 return HDF_ERR_IO;
325 }
326
327 number = (int16_t)(handle - TIMER_HANDLE_SHIFT);
328 if (number < 0) {
329 HDF_LOGE("%s: number[%d] invalid", __func__, number);
330 return HDF_ERR_INVALID_PARAM;
331 }
332 cfg.number = number;
333 ret = TimerCntrlGet(TimerCntrlOpen(number), &cfg.useconds, &cfg.isPeriod);
334 if (ret != HDF_SUCCESS) {
335 HDF_LOGE("%s: TimerCntrlGet failed!", __func__);
336 return ret;
337 }
338
339 if (!HdfSbufWriteBuffer(reply, &cfg, sizeof(cfg))) {
340 HDF_LOGE("%s: write buffer failed!", __func__);
341 return HDF_FAILURE;
342 }
343
344 return HDF_SUCCESS;
345 }
346
TimerIoDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)347 static int32_t TimerIoDispatch(struct HdfDeviceIoClient *client, int cmd,
348 struct HdfSBuf *data, struct HdfSBuf *reply)
349 {
350 int32_t ret;
351
352 switch (cmd) {
353 case TIMER_IO_OPEN:
354 ret = TimerIoOpen(data, reply);
355 break;
356 case TIMER_IO_CLOSE:
357 ret = TimerIoClose(data, reply);
358 break;
359 case TIMER_IO_START:
360 ret = TimerIoStart(data, reply);
361 break;
362 case TIMER_IO_STOP:
363 ret = TimerIoStop(data, reply);
364 break;
365 case TIMER_IO_SET:
366 ret = TimerIoSet(data, reply);
367 break;
368 case TIMER_IO_SETONCE:
369 ret = TimerIoSetOnce(data, reply);
370 break;
371 case TIMER_IO_GET:
372 ret = TimerIoGet(data, reply);
373 break;
374 default:
375 ret = HDF_ERR_NOT_SUPPORT;
376 HDF_LOGE("%s: cmd[%d] not support!", __func__, cmd);
377 break;
378 }
379 return ret;
380 }
381
TimerListRemoveAll(void)382 int32_t TimerListRemoveAll(void)
383 {
384 struct TimerCntrl *pos = NULL;
385 struct TimerCntrl *tmp = NULL;
386 struct TimerManager *manager = g_timerManager;
387
388 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
389 HDF_LOGE("%s: lock regulator manager fail", __func__);
390 return HDF_ERR_DEVICE_BUSY;
391 }
392
393 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->timerListHead, struct TimerCntrl, node) {
394 if ((pos->ops->Remove != NULL) && (pos->ops->Remove(pos) != HDF_SUCCESS)) {
395 HDF_LOGE("%s: remove %u failed", __func__, pos->info.number);
396 }
397 DListRemove(&pos->node);
398 (void)OsalMutexDestroy(&pos->lock);
399 OsalMemFree(pos);
400 }
401
402 (void)OsalMutexUnlock(&manager->lock);
403 HDF_LOGI("%s: remove all regulator success", __func__);
404 return HDF_SUCCESS;
405 }
406
TimerCntrlAdd(struct TimerCntrl * cntrl)407 int32_t TimerCntrlAdd(struct TimerCntrl *cntrl)
408 {
409 CHECK_NULL_PTR_RETURN_VALUE(cntrl, HDF_ERR_INVALID_PARAM);
410 CHECK_NULL_PTR_RETURN_VALUE(cntrl->ops, HDF_ERR_INVALID_PARAM);
411 struct TimerCntrl *pos = NULL;
412 struct TimerCntrl *tmp = NULL;
413 struct TimerManager *manager = g_timerManager;
414 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
415
416 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->timerListHead, struct TimerCntrl, node) {
417 if (cntrl->info.number == pos->info.number) {
418 HDF_LOGE("%s: timer[%u] existed", __func__, cntrl->info.number);
419 return HDF_FAILURE;
420 }
421 }
422
423 // init info
424 if (OsalMutexInit(&cntrl->lock) != HDF_SUCCESS) {
425 HDF_LOGE("%s: OsalMutexInit %u failed", __func__, cntrl->info.number);
426 return HDF_FAILURE;
427 }
428
429 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
430 HDF_LOGE("%s: OsalMutexLock %u failed", __func__, cntrl->info.number);
431 return HDF_ERR_DEVICE_BUSY;
432 }
433 DListInsertTail(&cntrl->node, &manager->timerListHead);
434 (void)OsalMutexUnlock(&manager->lock);
435 HDF_LOGI("%s: add timer number[%u] success", __func__, cntrl->info.number);
436
437 return HDF_SUCCESS;
438 }
439
TimerCntrlRemoveByNumber(const uint32_t number)440 int32_t TimerCntrlRemoveByNumber(const uint32_t number)
441 {
442 struct TimerCntrl *pos = NULL;
443 struct TimerCntrl *tmp = NULL;
444 struct TimerManager *manager = g_timerManager;
445 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
446
447 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
448 HDF_LOGE("%s: OsalMutexLock failed", __func__);
449 return HDF_ERR_DEVICE_BUSY;
450 }
451
452 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->timerListHead, struct TimerCntrl, node) {
453 if (number == pos->info.number) {
454 if ((pos->ops->Remove != NULL) && (pos->ops->Remove(pos) != HDF_SUCCESS)) {
455 HDF_LOGE("%s: remove %u failed", __func__, pos->info.number);
456 }
457 (void)OsalMutexDestroy(&pos->lock);
458 DListRemove(&pos->node);
459 OsalMemFree(pos);
460 break;
461 }
462 }
463
464 (void)OsalMutexUnlock(&manager->lock);
465 HDF_LOGI("%s: remove timer %u success", __func__, number);
466 return HDF_SUCCESS;
467 }
468
TimerManagerBind(struct HdfDeviceObject * device)469 static int32_t TimerManagerBind(struct HdfDeviceObject *device)
470 {
471 int32_t ret;
472 struct TimerManager *manager = NULL;
473
474 CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_OBJECT);
475
476 manager = (struct TimerManager *)OsalMemCalloc(sizeof(*manager));
477 if (manager == NULL) {
478 HDF_LOGE("%s: malloc manager fail!", __func__);
479 return HDF_ERR_MALLOC_FAIL;
480 }
481
482 ret = OsalMutexInit(&manager->lock);
483 if (ret != HDF_SUCCESS) {
484 HDF_LOGE("%s: mutex init fail:%d", __func__, ret);
485 OsalMemFree(manager);
486 manager = NULL;
487 return HDF_FAILURE;
488 }
489
490 manager->device = device;
491 device->service = &manager->service;
492 device->service->Dispatch = TimerIoDispatch;
493 DListHeadInit(&manager->timerListHead);
494 g_timerManager = manager;
495
496 HDF_LOGI("%s: success", __func__);
497 return HDF_SUCCESS;
498 }
499
TimerManagerInit(struct HdfDeviceObject * device)500 static int32_t TimerManagerInit(struct HdfDeviceObject *device)
501 {
502 (void)device;
503
504 HDF_LOGI("%s: success", __func__);
505 return HDF_SUCCESS;
506 }
507
TimerManagerRelease(struct HdfDeviceObject * device)508 static void TimerManagerRelease(struct HdfDeviceObject *device)
509 {
510 HDF_LOGI("%s: Enter!", __func__);
511 CHECK_NULL_PTR_RETURN(device);
512
513 if (TimerListRemoveAll() != HDF_SUCCESS) {
514 HDF_LOGE("%s: failed", __func__);
515 }
516
517 struct TimerManager *manager = (struct TimerManager *)device->service;
518 CHECK_NULL_PTR_RETURN(manager);
519 OsalMutexDestroy(&manager->lock);
520 OsalMemFree(manager);
521 g_timerManager = NULL;
522 }
523
524 struct HdfDriverEntry g_timerManagerEntry = {
525 .moduleVersion = 1,
526 .Bind = TimerManagerBind,
527 .Init = TimerManagerInit,
528 .Release = TimerManagerRelease,
529 .moduleName = "HDF_PLATFORM_TIMER_MANAGER",
530 };
531
532 HDF_INIT(g_timerManagerEntry);
533