1 /*
2  * Copyright (c) 2020 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "kal.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <time.h>
20 
21 #define KAL_TASK_NAME_LEN 32
22 #define LOSCFG_BASE_CORE_MS_PER_SECOND 1000
23 #define OS_SYS_NS_PER_SECOND 1000000000
24 
25 typedef struct {
26     timer_t timerPtr;
27     KalTimerType type;
28     unsigned int millisec;
29     KalTimerProc func;
30     union sigval arg;
31     int isRunning;
32 } KalTimer;
33 
KalFunction(union sigval kalTimer)34 static void KalFunction(union sigval kalTimer)
35 {
36     KalTimer* tmpPtr = (KalTimer *)(kalTimer.sival_ptr);
37     if (tmpPtr->type == KAL_TIMER_ONCE) {
38         tmpPtr->isRunning = 0;
39     }
40     tmpPtr->func(tmpPtr->arg);
41 }
42 
KalMs2TimeSpec(struct timespec * tp,unsigned int ms)43 static void KalMs2TimeSpec(struct timespec* tp, unsigned int ms)
44 {
45     tp->tv_sec = ms / LOSCFG_BASE_CORE_MS_PER_SECOND;
46     ms -= tp->tv_sec * LOSCFG_BASE_CORE_MS_PER_SECOND;
47     tp->tv_nsec = (long)(((unsigned long long)ms * OS_SYS_NS_PER_SECOND) / LOSCFG_BASE_CORE_MS_PER_SECOND);
48 }
49 
KalTimerCreate(KalTimerProc func,KalTimerType type,void * arg,unsigned int millisec)50 KalTimerId KalTimerCreate(KalTimerProc func, KalTimerType type, void* arg, unsigned int millisec)
51 {
52     struct sigevent evp = {0};
53     timer_t timer;
54     if ((func == NULL) || ((type != KAL_TIMER_ONCE) && (type != KAL_TIMER_PERIODIC))) {
55         return NULL;
56     }
57     KalTimer* kalTimer = (KalTimer *)malloc(sizeof(KalTimer));
58     if (kalTimer == NULL) {
59         return NULL;
60     }
61     kalTimer->func = func;
62     kalTimer->arg.sival_ptr = arg;
63     kalTimer->type = type;
64     evp.sigev_notify = SIGEV_THREAD;
65     evp.sigev_notify_function = KalFunction;
66     evp.sigev_value.sival_ptr = kalTimer;
67     int ret = timer_create(CLOCK_REALTIME, &evp, &timer);
68     if (ret != 0) {
69         free(kalTimer);
70         return NULL;
71     }
72     kalTimer->timerPtr = timer;
73     kalTimer->millisec = millisec;
74     kalTimer->isRunning = 0;
75     return (KalTimerId)kalTimer;
76 }
77 
KalTimerStart(KalTimerId timerId)78 KalErrCode KalTimerStart(KalTimerId timerId)
79 {
80     if (timerId == NULL) {
81         return KAL_ERR_PARA;
82     }
83     struct itimerspec ts = {0};
84     KalTimer* tmpPtr = (KalTimer *)timerId;
85     KalMs2TimeSpec(&ts.it_value, tmpPtr->millisec);
86     if (tmpPtr->type == KAL_TIMER_PERIODIC) {
87         KalMs2TimeSpec(&ts.it_interval, tmpPtr->millisec);
88     }
89     int ret = timer_settime(tmpPtr->timerPtr, 0, &ts, NULL);
90     if (ret != 0) {
91         return KAL_ERR_PARA;
92     }
93     if (tmpPtr->millisec != 0) {
94         tmpPtr->isRunning = 1;
95     }
96     return KAL_OK;
97 }
98 
KalTimerChange(KalTimerId timerId,unsigned int millisec)99 KalErrCode KalTimerChange(KalTimerId timerId, unsigned int millisec)
100 {
101     if (timerId == NULL) {
102         return KAL_ERR_PARA;
103     }
104     KalTimer* tmpPtr = (KalTimer *)timerId;
105     struct itimerspec ts = {0};
106     tmpPtr->millisec = millisec;
107     if (tmpPtr->isRunning == 1) {
108         KalMs2TimeSpec(&ts.it_value, millisec);
109         if (tmpPtr->type == KAL_TIMER_PERIODIC) {
110             KalMs2TimeSpec(&ts.it_interval, millisec);
111         }
112         int ret = timer_settime(tmpPtr->timerPtr, 0, &ts, NULL);
113         if (ret != 0) {
114             tmpPtr->isRunning = 0;
115             return KAL_ERR_INNER;
116         }
117         if (millisec == 0) {
118             tmpPtr->isRunning = 0;
119         }
120     }
121     return KAL_OK;
122 }
123 
KalTimerStop(KalTimerId timerId)124 KalErrCode KalTimerStop(KalTimerId timerId)
125 {
126     if (timerId == NULL) {
127         return KAL_ERR_PARA;
128     }
129     KalTimer* tmpPtr = (KalTimer *)timerId;
130     struct itimerspec ts = {0};
131     int ret = timer_settime(tmpPtr->timerPtr, 0, &ts, NULL);
132     if (ret != 0) {
133         return KAL_ERR_INNER;
134     }
135     tmpPtr->isRunning = 0;
136     return KAL_OK;
137 }
138 
KalTimerDelete(KalTimerId timerId)139 KalErrCode KalTimerDelete(KalTimerId timerId)
140 {
141     if (timerId == NULL) {
142         return KAL_ERR_PARA;
143     }
144     KalTimer* tmpPtr = (KalTimer *)timerId;
145     int ret = timer_delete(tmpPtr->timerPtr);
146     free(timerId);
147     return (ret != 0) ? KAL_ERR_INNER : KAL_OK;
148 }
149 
KalTimerIsRunning(KalTimerId timerId)150 unsigned int KalTimerIsRunning(KalTimerId timerId)
151 {
152     if (timerId == NULL) {
153         return 0;
154     }
155     return ((KalTimer *)timerId)->isRunning;
156 }