1 /*
2 * Copyright (c) 2020-2021 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("%s: HdfIoServiceBind failed\n", __func__);
33 return HDF_ERR_NOT_SUPPORT;
34 }
35
36 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
37 if (reply == NULL) {
38 HDF_LOGE("%s: failed to obtain reply", __func__);
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("%s: remote dispatch failed", __func__);
46 HdfIoServiceRecycle(service);
47 HdfSbufRecycle(reply);
48 return ret;
49 }
50
51 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
52 HDF_LOGE("%s: read buf failed", __func__);
53 HdfIoServiceRecycle(service);
54 HdfSbufRecycle(reply);
55 return HDF_ERR_IO;
56 }
57
58 if (len != sizeof(*config)) {
59 HDF_LOGE("%s: config size:%zu, read size:%u", __func__, 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("%s: memcpy buf failed", __func__);
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 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("%s: read config failed:%d", __func__, ret);
86 return NULL;
87 }
88
89 tester.handle = PwmOpen(tester.config.num);
90 if (tester.handle == NULL) {
91 HDF_LOGE("%s: open pwm device:%u failed", __func__, 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("%s: tester is NULL", __func__);
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("%s: Set number %u.", __func__, tester->config.cfg.number);
118 ret = PwmSetConfig(tester->handle, &(tester->config.cfg));
119 if (ret != HDF_SUCCESS) {
120 HDF_LOGE("%s: [PwmSetConfig] failed, ret %d.", __func__, ret);
121 return ret;
122 }
123
124 OsalSleep(OUTPUT_WAVES_DELAY);
125 tester->config.cfg.number = number;
126 HDF_LOGI("%s: Set number %u.", __func__, tester->config.cfg.number);
127 ret = PwmSetConfig(tester->handle, &(tester->config.cfg));
128 if (ret != HDF_SUCCESS) {
129 HDF_LOGE("%s: [PwmSetConfig] failed, ret %d.", __func__, ret);
130 return ret;
131 }
132
133 ret = PwmGetConfig(tester->handle, &cfg);
134 if (ret != HDF_SUCCESS) {
135 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
136 return ret;
137 }
138
139 if (memcmp(&cfg, &(tester->config.cfg), sizeof(cfg)) != 0) {
140 HDF_LOGE("%s: [memcmp_s] failed.", __func__);
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("%s: [PwmSetPeriod] failed, ret %d.", __func__, ret);
157 return ret;
158 }
159
160 ret = PwmGetConfig(tester->handle, &cfg);
161 if (ret != HDF_SUCCESS) {
162 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
163 return ret;
164 }
165
166 if (cfg.period != period) {
167 HDF_LOGE("%s: failed: cfg.period:%d period:%d", __func__, 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("%s: [PwmSetDuty] failed, ret %d.", __func__, ret);
184 return ret;
185 }
186
187 ret = PwmGetConfig(tester->handle, &cfg);
188 if (ret != HDF_SUCCESS) {
189 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
190 return ret;
191 }
192
193 if (cfg.duty != duty) {
194 HDF_LOGE("%s: failed.", __func__);
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("%s: Test [PwmSetPolarity] polarity %u.", __func__, tester->config.cfg.polarity);
208 ret = PwmSetPolarity(tester->handle, tester->config.cfg.polarity);
209 if (ret != HDF_SUCCESS) {
210 HDF_LOGE("%s: [PwmSetPolarity] failed, ret %d.", __func__, ret);
211 return ret;
212 }
213
214 tester->config.cfg.polarity = PWM_INVERTED_POLARITY;
215 HDF_LOGI("%s: Test [PwmSetPolarity] polarity %u.", __func__, tester->config.cfg.polarity);
216 ret = PwmSetPolarity(tester->handle, tester->config.cfg.polarity);
217 if (ret != HDF_SUCCESS) {
218 HDF_LOGE("%s: [PwmSetPolarity] failed, ret %d.", __func__, ret);
219 return ret;
220 }
221
222 ret = PwmGetConfig(tester->handle, &cfg);
223 if (ret != HDF_SUCCESS) {
224 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
225 return ret;
226 }
227
228 if (cfg.polarity != tester->config.cfg.polarity) {
229 HDF_LOGE("%s: failed.", __func__);
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("%s: [PwmDisable] failed, ret %d.", __func__, ret);
244 return ret;
245 }
246
247 HDF_LOGI("%s: Test [PwmEnable] enable.", __func__);
248 ret = PwmEnable(tester->handle);
249 if (ret != HDF_SUCCESS) {
250 HDF_LOGE("%s: [PwmEnable] failed, ret %d.", __func__, ret);
251 return ret;
252 }
253
254 ret = PwmGetConfig(tester->handle, &cfg);
255 if (ret != HDF_SUCCESS) {
256 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
257 return ret;
258 }
259
260 if (cfg.status == PWM_DISABLE_STATUS) {
261 HDF_LOGE("%s: failed", __func__);
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("%s: [PwmEnable] failed, ret %d.", __func__, ret);
276 return ret;
277 }
278
279 HDF_LOGI("%s: Test [PwmDisable] disable.", __func__);
280 ret = PwmDisable(tester->handle);
281 if (ret != HDF_SUCCESS) {
282 HDF_LOGE("%s: [PwmDisable] failed, ret %d.", __func__, ret);
283 return ret;
284 }
285
286 ret = PwmGetConfig(tester->handle, &cfg);
287 if (ret != HDF_SUCCESS) {
288 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
289 return ret;
290 }
291
292 if (cfg.status == PWM_ENABLE_STATUS) {
293 HDF_LOGE("%s: failed.", __func__);
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)PwmGetConfig(tester->handle, &cfg);
310 (void)PwmGetConfig(tester->handle, NULL);
311
312 (void)PwmSetPeriod(tester->handle, 0);
313 (void)PwmSetPeriod(tester->handle, TEST_PERIOD);
314
315 (void)PwmSetDuty(tester->handle, 0);
316 (void)PwmSetDuty(tester->handle, TEST_DUTY);
317
318 (void)PwmSetPolarity(tester->handle, 0);
319 (void)PwmSetPolarity(tester->handle, TEST_POLARITY);
320
321 (void)PwmEnable(tester->handle);
322 (void)PwmEnable(tester->handle);
323
324 (void)PwmDisable(tester->handle);
325 (void)PwmDisable(tester->handle);
326 HDF_LOGI("%s: success.", __func__);
327 return HDF_SUCCESS;
328 }
329
PwmIfPerformanceTest(struct PwmTester * tester)330 static int32_t PwmIfPerformanceTest(struct PwmTester *tester)
331 {
332 #ifdef __LITEOS__
333 // liteos the accuracy of the obtained time is too large and inaccurate.
334 if (tester == NULL) {
335 return HDF_FAILURE;
336 }
337 return HDF_SUCCESS;
338 #endif
339
340 struct PwmConfig cfg = {0};
341 uint64_t startMs;
342 uint64_t endMs;
343 uint64_t useTime; // ms
344
345 startMs = OsalGetSysTimeMs();
346 PwmGetConfig(tester->handle, &cfg);
347 endMs = OsalGetSysTimeMs();
348
349 useTime = endMs - startMs;
350 HDF_LOGI("----->interface performance test:[start:%lld(ms) - end:%lld(ms) = %lld (ms)] < 1ms[%d]\r\n",
351 startMs, endMs, useTime, useTime < 1 ? true : false);
352 return HDF_SUCCESS;
353 }
354
355 struct PwmTestEntry {
356 int cmd;
357 int32_t (*func)(struct PwmTester *tester);
358 };
359
360 static struct PwmTestEntry g_entry[] = {
361 { PWM_SET_PERIOD_TEST, PwmSetPeriodTest },
362 { PWM_SET_DUTY_TEST, PwmSetDutyTest },
363 { PWM_SET_POLARITY_TEST, PwmSetPolarityTest },
364 { PWM_ENABLE_TEST, PwmEnableTest },
365 { PWM_DISABLE_TEST, PwmDisableTest },
366 { PWM_SET_GET_CONFIG_TEST, PwmSetGetConfigTest },
367 { PWM_RELIABILITY_TEST, PwmReliabilityTest },
368 { PWM_IF_PERFORMANCE_TEST, PwmIfPerformanceTest },
369 };
370
PwmTestExecute(int cmd)371 int32_t PwmTestExecute(int cmd)
372 {
373 uint32_t i;
374 int32_t ret;
375 struct PwmTester *tester = NULL;
376
377 if (cmd > PWM_TEST_CMD_MAX) {
378 HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
379 return HDF_ERR_NOT_SUPPORT;
380 }
381
382 tester = PwmTesterGet();
383 if (tester == NULL) {
384 HDF_LOGE("%s: get tester failed", __func__);
385 return HDF_ERR_INVALID_OBJECT;
386 }
387
388 // At first test case.
389 if (cmd == PWM_SET_PERIOD_TEST) {
390 ret = PwmGetConfig(tester->handle, &(tester->originCfg));
391 if (ret != HDF_SUCCESS) {
392 HDF_LOGE("%s: [PwmGetConfig] failed, ret %d.", __func__, ret);
393 HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
394 PwmTesterPut(tester);
395 return ret;
396 }
397 }
398
399 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
400 if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
401 continue;
402 }
403 ret = g_entry[i].func(tester);
404 break;
405 }
406
407 // At last test case.
408 if (cmd == PWM_DISABLE_TEST) {
409 PwmSetConfig(tester->handle, &(tester->originCfg));
410 }
411
412 HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
413 PwmTesterPut(tester);
414 return ret;
415 }
416