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