10e98b08fSopenharmony_ci/*
20e98b08fSopenharmony_ci * Copyright (c) 2020 Huawei Device Co., Ltd.
30e98b08fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
40e98b08fSopenharmony_ci * you may not use this file except in compliance with the License.
50e98b08fSopenharmony_ci * You may obtain a copy of the License at
60e98b08fSopenharmony_ci *
70e98b08fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
80e98b08fSopenharmony_ci *
90e98b08fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
100e98b08fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
110e98b08fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120e98b08fSopenharmony_ci * See the License for the specific language governing permissions and
130e98b08fSopenharmony_ci * limitations under the License.
140e98b08fSopenharmony_ci */
150e98b08fSopenharmony_ci
160e98b08fSopenharmony_ci#include "kal.h"
170e98b08fSopenharmony_ci#include <stdio.h>
180e98b08fSopenharmony_ci#include <stdlib.h>
190e98b08fSopenharmony_ci#include <time.h>
200e98b08fSopenharmony_ci
210e98b08fSopenharmony_ci#define KAL_TASK_NAME_LEN 32
220e98b08fSopenharmony_ci#define LOSCFG_BASE_CORE_MS_PER_SECOND 1000
230e98b08fSopenharmony_ci#define OS_SYS_NS_PER_SECOND 1000000000
240e98b08fSopenharmony_ci
250e98b08fSopenharmony_citypedef struct {
260e98b08fSopenharmony_ci    timer_t timerPtr;
270e98b08fSopenharmony_ci    KalTimerType type;
280e98b08fSopenharmony_ci    unsigned int millisec;
290e98b08fSopenharmony_ci    KalTimerProc func;
300e98b08fSopenharmony_ci    union sigval arg;
310e98b08fSopenharmony_ci    int isRunning;
320e98b08fSopenharmony_ci} KalTimer;
330e98b08fSopenharmony_ci
340e98b08fSopenharmony_cistatic void KalFunction(union sigval kalTimer)
350e98b08fSopenharmony_ci{
360e98b08fSopenharmony_ci    KalTimer* tmpPtr = (KalTimer *)(kalTimer.sival_ptr);
370e98b08fSopenharmony_ci    if (tmpPtr->type == KAL_TIMER_ONCE) {
380e98b08fSopenharmony_ci        tmpPtr->isRunning = 0;
390e98b08fSopenharmony_ci    }
400e98b08fSopenharmony_ci    tmpPtr->func(tmpPtr->arg);
410e98b08fSopenharmony_ci}
420e98b08fSopenharmony_ci
430e98b08fSopenharmony_cistatic void KalMs2TimeSpec(struct timespec* tp, unsigned int ms)
440e98b08fSopenharmony_ci{
450e98b08fSopenharmony_ci    tp->tv_sec = ms / LOSCFG_BASE_CORE_MS_PER_SECOND;
460e98b08fSopenharmony_ci    ms -= tp->tv_sec * LOSCFG_BASE_CORE_MS_PER_SECOND;
470e98b08fSopenharmony_ci    tp->tv_nsec = (long)(((unsigned long long)ms * OS_SYS_NS_PER_SECOND) / LOSCFG_BASE_CORE_MS_PER_SECOND);
480e98b08fSopenharmony_ci}
490e98b08fSopenharmony_ci
500e98b08fSopenharmony_ciKalTimerId KalTimerCreate(KalTimerProc func, KalTimerType type, void* arg, unsigned int millisec)
510e98b08fSopenharmony_ci{
520e98b08fSopenharmony_ci    struct sigevent evp = {0};
530e98b08fSopenharmony_ci    timer_t timer;
540e98b08fSopenharmony_ci    if ((func == NULL) || ((type != KAL_TIMER_ONCE) && (type != KAL_TIMER_PERIODIC))) {
550e98b08fSopenharmony_ci        return NULL;
560e98b08fSopenharmony_ci    }
570e98b08fSopenharmony_ci    KalTimer* kalTimer = (KalTimer *)malloc(sizeof(KalTimer));
580e98b08fSopenharmony_ci    if (kalTimer == NULL) {
590e98b08fSopenharmony_ci        return NULL;
600e98b08fSopenharmony_ci    }
610e98b08fSopenharmony_ci    kalTimer->func = func;
620e98b08fSopenharmony_ci    kalTimer->arg.sival_ptr = arg;
630e98b08fSopenharmony_ci    kalTimer->type = type;
640e98b08fSopenharmony_ci    evp.sigev_notify = SIGEV_THREAD;
650e98b08fSopenharmony_ci    evp.sigev_notify_function = KalFunction;
660e98b08fSopenharmony_ci    evp.sigev_value.sival_ptr = kalTimer;
670e98b08fSopenharmony_ci    int ret = timer_create(CLOCK_REALTIME, &evp, &timer);
680e98b08fSopenharmony_ci    if (ret != 0) {
690e98b08fSopenharmony_ci        free(kalTimer);
700e98b08fSopenharmony_ci        return NULL;
710e98b08fSopenharmony_ci    }
720e98b08fSopenharmony_ci    kalTimer->timerPtr = timer;
730e98b08fSopenharmony_ci    kalTimer->millisec = millisec;
740e98b08fSopenharmony_ci    kalTimer->isRunning = 0;
750e98b08fSopenharmony_ci    return (KalTimerId)kalTimer;
760e98b08fSopenharmony_ci}
770e98b08fSopenharmony_ci
780e98b08fSopenharmony_ciKalErrCode KalTimerStart(KalTimerId timerId)
790e98b08fSopenharmony_ci{
800e98b08fSopenharmony_ci    if (timerId == NULL) {
810e98b08fSopenharmony_ci        return KAL_ERR_PARA;
820e98b08fSopenharmony_ci    }
830e98b08fSopenharmony_ci    struct itimerspec ts = {0};
840e98b08fSopenharmony_ci    KalTimer* tmpPtr = (KalTimer *)timerId;
850e98b08fSopenharmony_ci    KalMs2TimeSpec(&ts.it_value, tmpPtr->millisec);
860e98b08fSopenharmony_ci    if (tmpPtr->type == KAL_TIMER_PERIODIC) {
870e98b08fSopenharmony_ci        KalMs2TimeSpec(&ts.it_interval, tmpPtr->millisec);
880e98b08fSopenharmony_ci    }
890e98b08fSopenharmony_ci    int ret = timer_settime(tmpPtr->timerPtr, 0, &ts, NULL);
900e98b08fSopenharmony_ci    if (ret != 0) {
910e98b08fSopenharmony_ci        return KAL_ERR_PARA;
920e98b08fSopenharmony_ci    }
930e98b08fSopenharmony_ci    if (tmpPtr->millisec != 0) {
940e98b08fSopenharmony_ci        tmpPtr->isRunning = 1;
950e98b08fSopenharmony_ci    }
960e98b08fSopenharmony_ci    return KAL_OK;
970e98b08fSopenharmony_ci}
980e98b08fSopenharmony_ci
990e98b08fSopenharmony_ciKalErrCode KalTimerChange(KalTimerId timerId, unsigned int millisec)
1000e98b08fSopenharmony_ci{
1010e98b08fSopenharmony_ci    if (timerId == NULL) {
1020e98b08fSopenharmony_ci        return KAL_ERR_PARA;
1030e98b08fSopenharmony_ci    }
1040e98b08fSopenharmony_ci    KalTimer* tmpPtr = (KalTimer *)timerId;
1050e98b08fSopenharmony_ci    struct itimerspec ts = {0};
1060e98b08fSopenharmony_ci    tmpPtr->millisec = millisec;
1070e98b08fSopenharmony_ci    if (tmpPtr->isRunning == 1) {
1080e98b08fSopenharmony_ci        KalMs2TimeSpec(&ts.it_value, millisec);
1090e98b08fSopenharmony_ci        if (tmpPtr->type == KAL_TIMER_PERIODIC) {
1100e98b08fSopenharmony_ci            KalMs2TimeSpec(&ts.it_interval, millisec);
1110e98b08fSopenharmony_ci        }
1120e98b08fSopenharmony_ci        int ret = timer_settime(tmpPtr->timerPtr, 0, &ts, NULL);
1130e98b08fSopenharmony_ci        if (ret != 0) {
1140e98b08fSopenharmony_ci            tmpPtr->isRunning = 0;
1150e98b08fSopenharmony_ci            return KAL_ERR_INNER;
1160e98b08fSopenharmony_ci        }
1170e98b08fSopenharmony_ci        if (millisec == 0) {
1180e98b08fSopenharmony_ci            tmpPtr->isRunning = 0;
1190e98b08fSopenharmony_ci        }
1200e98b08fSopenharmony_ci    }
1210e98b08fSopenharmony_ci    return KAL_OK;
1220e98b08fSopenharmony_ci}
1230e98b08fSopenharmony_ci
1240e98b08fSopenharmony_ciKalErrCode KalTimerStop(KalTimerId timerId)
1250e98b08fSopenharmony_ci{
1260e98b08fSopenharmony_ci    if (timerId == NULL) {
1270e98b08fSopenharmony_ci        return KAL_ERR_PARA;
1280e98b08fSopenharmony_ci    }
1290e98b08fSopenharmony_ci    KalTimer* tmpPtr = (KalTimer *)timerId;
1300e98b08fSopenharmony_ci    struct itimerspec ts = {0};
1310e98b08fSopenharmony_ci    int ret = timer_settime(tmpPtr->timerPtr, 0, &ts, NULL);
1320e98b08fSopenharmony_ci    if (ret != 0) {
1330e98b08fSopenharmony_ci        return KAL_ERR_INNER;
1340e98b08fSopenharmony_ci    }
1350e98b08fSopenharmony_ci    tmpPtr->isRunning = 0;
1360e98b08fSopenharmony_ci    return KAL_OK;
1370e98b08fSopenharmony_ci}
1380e98b08fSopenharmony_ci
1390e98b08fSopenharmony_ciKalErrCode KalTimerDelete(KalTimerId timerId)
1400e98b08fSopenharmony_ci{
1410e98b08fSopenharmony_ci    if (timerId == NULL) {
1420e98b08fSopenharmony_ci        return KAL_ERR_PARA;
1430e98b08fSopenharmony_ci    }
1440e98b08fSopenharmony_ci    KalTimer* tmpPtr = (KalTimer *)timerId;
1450e98b08fSopenharmony_ci    int ret = timer_delete(tmpPtr->timerPtr);
1460e98b08fSopenharmony_ci    free(timerId);
1470e98b08fSopenharmony_ci    return (ret != 0) ? KAL_ERR_INNER : KAL_OK;
1480e98b08fSopenharmony_ci}
1490e98b08fSopenharmony_ci
1500e98b08fSopenharmony_ciunsigned int KalTimerIsRunning(KalTimerId timerId)
1510e98b08fSopenharmony_ci{
1520e98b08fSopenharmony_ci    if (timerId == NULL) {
1530e98b08fSopenharmony_ci        return 0;
1540e98b08fSopenharmony_ci    }
1550e98b08fSopenharmony_ci    return ((KalTimer *)timerId)->isRunning;
1560e98b08fSopenharmony_ci}