1 /*
2  * Copyright (c) 2020-2023 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 "pwm_test.h"
10 #include "device_resource_if.h"
11 #include "hdf_io_service_if.h"
12 #include "hdf_log.h"
13 #include "osal_mem.h"
14 #include "osal_time.h"
15 #include "securec.h"
16 
17 #define HDF_LOG_TAG           pwm_test
18 #define SEQ_OUTPUT_DELAY      100 /* Delay time of sequential output, unit: ms */
19 #define OUTPUT_WAVES_DELAY    1 /* Delay time of waves output, unit: second */
20 #define TEST_WAVES_NUMBER     10 /* The number of waves for test. */
21 
PwmTesterGetConfig(struct PwmTestConfig * config)22 static int32_t PwmTesterGetConfig(struct PwmTestConfig *config)
23 {
24     int32_t ret;
25     struct HdfSBuf *reply = NULL;
26     struct HdfIoService *service = NULL;
27     const void *buf = NULL;
28     uint32_t len;
29 
30     service = HdfIoServiceBind("PWM_TEST");
31     if ((service == NULL) || (service->dispatcher == NULL) || (service->dispatcher->Dispatch == NULL)) {
32         HDF_LOGE("PwmTesterGetConfig: service bind fail!\n");
33         return HDF_ERR_NOT_SUPPORT;
34     }
35 
36     reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
37     if (reply == NULL) {
38         HDF_LOGE("PwmTesterGetConfig: fail to obtain reply!");
39         HdfIoServiceRecycle(service);
40         return HDF_ERR_MALLOC_FAIL;
41     }
42 
43     ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
44     if (ret != HDF_SUCCESS) {
45         HDF_LOGE("PwmTesterGetConfig: remote dispatch fail, ret: %d!", ret);
46         HdfIoServiceRecycle(service);
47         HdfSbufRecycle(reply);
48         return ret;
49     }
50 
51     if (!HdfSbufReadBuffer(reply, &buf, &len)) {
52         HDF_LOGE("PwmTesterGetConfig: read buf fail!");
53         HdfIoServiceRecycle(service);
54         HdfSbufRecycle(reply);
55         return HDF_ERR_IO;
56     }
57 
58     if (len != sizeof(*config)) {
59         HDF_LOGE("PwmTesterGetConfig: config size:%zu, read size:%u!", sizeof(*config), len);
60         HdfIoServiceRecycle(service);
61         HdfSbufRecycle(reply);
62         return HDF_ERR_IO;
63     }
64 
65     if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
66         HDF_LOGE("PwmTesterGetConfig: memcpy buf fail!");
67         HdfIoServiceRecycle(service);
68         HdfSbufRecycle(reply);
69         return HDF_ERR_IO;
70     }
71 
72     HdfIoServiceRecycle(service);
73     HdfSbufRecycle(reply);
74     return HDF_SUCCESS;
75 }
76 
PwmTesterGet(void)77 static struct PwmTester *PwmTesterGet(void)
78 {
79     int32_t ret;
80     static struct PwmTester tester;
81 
82     OsalMSleep(SEQ_OUTPUT_DELAY);
83     ret = PwmTesterGetConfig(&tester.config);
84     if (ret != HDF_SUCCESS) {
85         HDF_LOGE("PwmTesterGet: read config fail, ret: %d!", ret);
86         return NULL;
87     }
88 
89     tester.handle = PwmOpen(tester.config.num);
90     if (tester.handle == NULL) {
91         HDF_LOGE("PwmTesterGet: open pwm device:%u fail!", tester.config.num);
92         return NULL;
93     }
94 
95     return &tester;
96 }
97 
PwmTesterPut(struct PwmTester * tester)98 static void PwmTesterPut(struct PwmTester *tester)
99 {
100     if (tester == NULL) {
101         HDF_LOGE("PwmTesterPut: tester is null!");
102         return;
103     }
104     PwmClose(tester->handle);
105     tester->handle = NULL;
106     OsalMSleep(SEQ_OUTPUT_DELAY);
107 }
108 
PwmSetGetConfigTest(struct PwmTester * tester)109 static int32_t PwmSetGetConfigTest(struct PwmTester *tester)
110 {
111     int32_t ret;
112     struct PwmConfig cfg = {0};
113     uint32_t number;
114 
115     number = tester->config.cfg.number;
116     tester->config.cfg.number = ((number > 0) ? 0 : TEST_WAVES_NUMBER);
117     HDF_LOGI("PwmSetGetConfigTest: set number %u!", tester->config.cfg.number);
118     ret = PwmSetConfig(tester->handle, &(tester->config.cfg));
119     if (ret != HDF_SUCCESS) {
120         HDF_LOGE("PwmSetGetConfigTest: [PwmSetConfig] fail, ret: %d!", ret);
121         return ret;
122     }
123 
124     OsalSleep(OUTPUT_WAVES_DELAY);
125     tester->config.cfg.number = number;
126     HDF_LOGI("PwmSetGetConfigTest: Set number %u.", tester->config.cfg.number);
127     ret = PwmSetConfig(tester->handle, &(tester->config.cfg));
128     if (ret != HDF_SUCCESS) {
129         HDF_LOGE("PwmSetGetConfigTest: [PwmSetConfig] fail, ret: %d!", ret);
130         return ret;
131     }
132 
133     ret = PwmGetConfig(tester->handle, &cfg);
134     if (ret != HDF_SUCCESS) {
135         HDF_LOGE("PwmSetGetConfigTest: [PwmGetConfig] fail, ret: %d!", ret);
136         return ret;
137     }
138 
139     if (memcmp(&cfg, &(tester->config.cfg), sizeof(cfg)) != 0) {
140         HDF_LOGE("PwmSetGetConfigTest: [memcmp_s] fail!");
141         return HDF_FAILURE;
142     }
143 
144     return HDF_SUCCESS;
145 }
146 
PwmSetPeriodTest(struct PwmTester * tester)147 static int32_t PwmSetPeriodTest(struct PwmTester *tester)
148 {
149     int32_t ret;
150     struct PwmConfig cfg = {0};
151     uint32_t period;
152 
153     period = tester->config.cfg.period + tester->originCfg.period;
154     ret = PwmSetPeriod(tester->handle, period);
155     if (ret != HDF_SUCCESS) {
156         HDF_LOGE("PwmSetPeriodTest: [PwmSetPeriod] fail, ret: %d!", ret);
157         return ret;
158     }
159 
160     ret = PwmGetConfig(tester->handle, &cfg);
161     if (ret != HDF_SUCCESS) {
162         HDF_LOGE("PwmSetPeriodTest: [PwmGetConfig] fail, ret: %d!", ret);
163         return ret;
164     }
165 
166     if (cfg.period != period) {
167         HDF_LOGE("PwmSetPeriodTest: fail: cfg.period:%u period:%u!", cfg.period, period);
168         return HDF_FAILURE;
169     }
170 
171     return HDF_SUCCESS;
172 }
173 
PwmSetDutyTest(struct PwmTester * tester)174 static int32_t PwmSetDutyTest(struct PwmTester *tester)
175 {
176     int32_t ret;
177     struct PwmConfig cfg = {0};
178     uint32_t duty;
179 
180     duty = tester->config.cfg.duty+ tester->originCfg.duty;
181     ret = PwmSetDuty(tester->handle, duty);
182     if (ret != HDF_SUCCESS) {
183         HDF_LOGE("PwmSetDutyTest: [PwmSetDuty] fail, ret: %d!", ret);
184         return ret;
185     }
186 
187     ret = PwmGetConfig(tester->handle, &cfg);
188     if (ret != HDF_SUCCESS) {
189         HDF_LOGE("PwmSetDutyTest: [PwmGetConfig] fail, ret: %d!", ret);
190         return ret;
191     }
192 
193     if (cfg.duty != duty) {
194         HDF_LOGE("PwmSetDutyTest: fail!");
195         return HDF_FAILURE;
196     }
197 
198     return HDF_SUCCESS;
199 }
200 
PwmSetPolarityTest(struct PwmTester * tester)201 static int32_t PwmSetPolarityTest(struct PwmTester *tester)
202 {
203     int32_t ret;
204     struct PwmConfig cfg = {0};
205 
206     tester->config.cfg.polarity = PWM_NORMAL_POLARITY;
207     HDF_LOGI("PwmSetPolarityTest: Test [PwmSetPolarity] polarity %u!", tester->config.cfg.polarity);
208     ret = PwmSetPolarity(tester->handle, tester->config.cfg.polarity);
209     if (ret != HDF_SUCCESS) {
210         HDF_LOGE("PwmSetPolarityTest: [PwmSetPolarity] fail, ret: %d!", ret);
211         return ret;
212     }
213 
214     tester->config.cfg.polarity = PWM_INVERTED_POLARITY;
215     HDF_LOGI("PwmSetPolarityTest: Test [PwmSetPolarity] polarity %u!", tester->config.cfg.polarity);
216     ret = PwmSetPolarity(tester->handle, tester->config.cfg.polarity);
217     if (ret != HDF_SUCCESS) {
218         HDF_LOGE("PwmSetPolarityTest: [PwmSetPolarity] fail, ret: %d!", ret);
219         return ret;
220     }
221 
222     ret = PwmGetConfig(tester->handle, &cfg);
223     if (ret != HDF_SUCCESS) {
224         HDF_LOGE("PwmSetPolarityTest: [PwmGetConfig] fail, ret: %d!", ret);
225         return ret;
226     }
227 
228     if (cfg.polarity != tester->config.cfg.polarity) {
229         HDF_LOGE("PwmSetPolarityTest: fail!");
230         return HDF_FAILURE;
231     }
232 
233     return HDF_SUCCESS;
234 }
235 
PwmEnableTest(struct PwmTester * tester)236 static int32_t PwmEnableTest(struct PwmTester *tester)
237 {
238     int32_t ret;
239     struct PwmConfig cfg = {0};
240 
241     ret = PwmDisable(tester->handle);
242     if (ret != HDF_SUCCESS) {
243         HDF_LOGE("PwmEnableTest: [PwmDisable] fail, ret: %d!", ret);
244         return ret;
245     }
246 
247     HDF_LOGI("PwmEnableTest: Test [PwmEnable] enable!");
248     ret = PwmEnable(tester->handle);
249     if (ret != HDF_SUCCESS) {
250         HDF_LOGE("PwmEnableTest: [PwmEnable] fail, ret: %d!", ret);
251         return ret;
252     }
253 
254     ret = PwmGetConfig(tester->handle, &cfg);
255     if (ret != HDF_SUCCESS) {
256         HDF_LOGE("PwmEnableTest: [PwmGetConfig] fail, ret: %d!", ret);
257         return ret;
258     }
259 
260     if (cfg.status == PWM_DISABLE_STATUS) {
261         HDF_LOGE("PwmEnableTest: fail!");
262         return HDF_FAILURE;
263     }
264 
265     return HDF_SUCCESS;
266 }
267 
PwmDisableTest(struct PwmTester * tester)268 static int32_t PwmDisableTest(struct PwmTester *tester)
269 {
270     int32_t ret;
271     struct PwmConfig cfg = {0};
272 
273     ret = PwmEnable(tester->handle);
274     if (ret != HDF_SUCCESS) {
275         HDF_LOGE("PwmDisableTest: [PwmEnable] fail, ret: %d!", ret);
276         return ret;
277     }
278 
279     HDF_LOGI("PwmDisableTest: Test [PwmDisable] disable!");
280     ret = PwmDisable(tester->handle);
281     if (ret != HDF_SUCCESS) {
282         HDF_LOGE("PwmDisableTest: [PwmDisable] fail, ret: %d!", ret);
283         return ret;
284     }
285 
286     ret = PwmGetConfig(tester->handle, &cfg);
287     if (ret != HDF_SUCCESS) {
288         HDF_LOGE("PwmDisableTest: [PwmGetConfig] fail, ret: %d!", ret);
289         return ret;
290     }
291 
292     if (cfg.status == PWM_ENABLE_STATUS) {
293         HDF_LOGE("PwmDisableTest: fail!");
294         return HDF_FAILURE;
295     }
296 
297     return HDF_SUCCESS;
298 }
299 
300 #define TEST_PERIOD 2147483647
301 #define TEST_DUTY 2147483647
302 #define TEST_POLARITY 10
PwmReliabilityTest(struct PwmTester * tester)303 static int32_t PwmReliabilityTest(struct PwmTester *tester)
304 {
305     struct PwmConfig cfg = {0};
306 
307     (void)PwmSetConfig(tester->handle, &(tester->config.cfg));
308     (void)PwmSetConfig(tester->handle, NULL);
309     (void)PwmSetConfig(NULL, &(tester->config.cfg));
310     (void)PwmGetConfig(tester->handle, &cfg);
311     (void)PwmGetConfig(tester->handle, NULL);
312     (void)PwmGetConfig(NULL, &cfg);
313 
314     (void)PwmSetPeriod(tester->handle, 0);
315     (void)PwmSetPeriod(tester->handle, TEST_PERIOD);
316     (void)PwmSetPeriod(NULL, TEST_PERIOD);
317 
318     (void)PwmSetDuty(tester->handle, 0);
319     (void)PwmSetDuty(tester->handle, TEST_DUTY);
320     (void)PwmSetDuty(NULL, TEST_DUTY);
321 
322     (void)PwmSetPolarity(tester->handle, 0);
323     (void)PwmSetPolarity(tester->handle, TEST_POLARITY);
324     (void)PwmSetPolarity(NULL, TEST_POLARITY);
325 
326     (void)PwmEnable(tester->handle);
327     (void)PwmEnable(NULL);
328 
329     (void)PwmDisable(tester->handle);
330     (void)PwmDisable(NULL);
331     HDF_LOGI("PwmReliabilityTest: success!");
332     return HDF_SUCCESS;
333 }
334 
PwmIfPerformanceTest(struct PwmTester * tester)335 static int32_t PwmIfPerformanceTest(struct PwmTester *tester)
336 {
337 #ifdef __LITEOS__
338     // liteos the accuracy of the obtained time is too large and inaccurate.
339     if (tester == NULL) {
340         return HDF_FAILURE;
341     }
342     return HDF_SUCCESS;
343 #endif
344 
345     struct PwmConfig cfg = {0};
346     uint64_t startMs;
347     uint64_t endMs;
348     uint64_t useTime;    // ms
349 
350     startMs = OsalGetSysTimeMs();
351     PwmGetConfig(tester->handle, &cfg);
352     endMs = OsalGetSysTimeMs();
353 
354     useTime = endMs - startMs;
355     HDF_LOGI("PwmIfPerformanceTest: ----->interface performance test:[start - end] < 1ms[%s]\r\n",
356         useTime < 1 ? "yes" : "no");
357     return HDF_SUCCESS;
358 }
359 
360 struct PwmTestEntry {
361     int cmd;
362     int32_t (*func)(struct PwmTester *tester);
363 };
364 
365 static struct PwmTestEntry g_entry[] = {
366     { PWM_SET_PERIOD_TEST, PwmSetPeriodTest },
367     { PWM_SET_DUTY_TEST, PwmSetDutyTest },
368     { PWM_SET_POLARITY_TEST, PwmSetPolarityTest },
369     { PWM_ENABLE_TEST, PwmEnableTest },
370     { PWM_DISABLE_TEST, PwmDisableTest },
371     { PWM_SET_GET_CONFIG_TEST, PwmSetGetConfigTest },
372     { PWM_RELIABILITY_TEST, PwmReliabilityTest },
373     { PWM_IF_PERFORMANCE_TEST, PwmIfPerformanceTest },
374 };
375 
PwmTestExecute(int cmd)376 int32_t PwmTestExecute(int cmd)
377 {
378     uint32_t i;
379     int32_t ret;
380     struct PwmTester *tester = NULL;
381 
382     if (cmd > PWM_TEST_CMD_MAX) {
383         HDF_LOGE("PwmTestExecute: invalid cmd:%d!", cmd);
384         return HDF_ERR_NOT_SUPPORT;
385     }
386 
387     tester = PwmTesterGet();
388     if (tester == NULL) {
389         HDF_LOGE("PwmTestExecute: get tester fail!");
390         return HDF_ERR_INVALID_OBJECT;
391     }
392 
393     // At first test case.
394     if (cmd == PWM_SET_PERIOD_TEST) {
395         ret = PwmGetConfig(tester->handle, &(tester->originCfg));
396         if (ret != HDF_SUCCESS) {
397             HDF_LOGE("PwmTestExecute: [PwmGetConfig] fail, ret: %d!", ret);
398             HDF_LOGI("[PwmTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
399             PwmTesterPut(tester);
400             return ret;
401         }
402     }
403 
404     for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
405         if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
406             continue;
407         }
408         ret = g_entry[i].func(tester);
409         break;
410     }
411 
412     // At last test case.
413     if (cmd == PWM_DISABLE_TEST) {
414         PwmSetConfig(tester->handle, &(tester->originCfg));
415     }
416 
417     HDF_LOGI("[PwmTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
418     PwmTesterPut(tester);
419     return ret;
420 }
421