1 /*
2 * Copyright (c) 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 "dac_test.h"
10 #include "hdf_io_service_if.h"
11 #include "hdf_log.h"
12 #include "osal_thread.h"
13 #include "osal_time.h"
14 #include "securec.h"
15
16 #define HDF_LOG_TAG dac_test_c
17 #define DAC_TEST_WAIT_TIMES 100
18 #define TEST_DAC_VAL_NUM 50
19 #define DAC_TEST_STACK_SIZE (1024 * 64)
20 #define DAC_TEST_WAIT_TIMEOUT 20
21
DacTestGetConfig(struct DacTestConfig * config)22 static int32_t DacTestGetConfig(struct DacTestConfig *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("DAC_TEST");
31 if (service == NULL) {
32 return HDF_ERR_NOT_SUPPORT;
33 }
34
35 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
36 if (reply == NULL) {
37 HDF_LOGE("%s: failed to obtain reply", __func__);
38 return HDF_ERR_MALLOC_FAIL;
39 }
40
41 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
42 if (ret != HDF_SUCCESS) {
43 HDF_LOGE("%s: remote dispatch failed", __func__);
44 HdfSbufRecycle(reply);
45 return ret;
46 }
47
48 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
49 HDF_LOGE("%s: read buf failed", __func__);
50 HdfSbufRecycle(reply);
51 return HDF_ERR_IO;
52 }
53
54 if (len != sizeof(*config)) {
55 HDF_LOGE("%s: config size:%zu, read size:%u", __func__, sizeof(*config), len);
56 HdfSbufRecycle(reply);
57 return HDF_ERR_IO;
58 }
59
60 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
61 HDF_LOGE("%s: memcpy buf failed", __func__);
62 HdfSbufRecycle(reply);
63 return HDF_ERR_IO;
64 }
65 HdfSbufRecycle(reply);
66 HDF_LOGD("%s: exit", __func__);
67 return HDF_SUCCESS;
68 }
69
DacTesterGet(void)70 struct DacTester *DacTesterGet(void)
71 {
72 int32_t ret;
73 static struct DacTester tester;
74
75 ret = DacTestGetConfig(&tester.config);
76 if (ret != HDF_SUCCESS) {
77 HDF_LOGE("%s: write config failed:%d", __func__, ret);
78 return NULL;
79 }
80 tester.handle = DacOpen(tester.config.devNum);
81 if (tester.handle == NULL) {
82 HDF_LOGE("%s: open dac device:%u failed", __func__, tester.config.devNum);
83 return NULL;
84 }
85 return &tester;
86 }
87
DacTesterPut(struct DacTester * tester)88 static void DacTesterPut(struct DacTester *tester)
89 {
90 if (tester == NULL) {
91 HDF_LOGE("%s: tester is NULL", __func__);
92 return;
93 }
94 DacClose(tester->handle);
95 tester->handle = NULL;
96 }
97
DacTestWrite(void)98 int32_t DacTestWrite(void)
99 {
100 struct DacTester *tester = NULL;
101 uint32_t value[TEST_DAC_VAL_NUM];
102 int32_t ret;
103 int i;
104
105 tester = DacTesterGet();
106 if (tester == NULL || tester->handle == NULL) {
107 HDF_LOGE("%s: get tester failed", __func__);
108 return HDF_ERR_INVALID_OBJECT;
109 }
110 for (i = 0; i < TEST_DAC_VAL_NUM; i++) {
111 value[i] = i;
112 ret = DacWrite(tester->handle, tester->config.channel, value[i]);
113 if (ret != HDF_SUCCESS) {
114 HDF_LOGE("%s: write value failed:%u, ret:%d", __func__, value[i], ret);
115 DacTesterPut(tester);
116 return HDF_ERR_IO;
117 }
118 }
119
120 DacTesterPut(tester);
121 return HDF_SUCCESS;
122 }
123
DacTestThreadFunc(void * param)124 static int DacTestThreadFunc(void *param)
125 {
126 struct DacTester *tester = NULL;
127 uint32_t val;
128 uint32_t i;
129 int32_t ret;
130
131 tester = DacTesterGet();
132 if (tester == NULL) {
133 HDF_LOGE("%s: get tester failed", __func__);
134 *((int32_t *)param) = 1;
135 return HDF_ERR_INVALID_OBJECT;
136 }
137 for (i = 0; i < DAC_TEST_WAIT_TIMES; i++) {
138 val = i;
139 ret = DacWrite(tester->handle, tester->config.channel, val);
140 if (ret != HDF_SUCCESS) {
141 HDF_LOGE("%s: DacWrite failed, ret:%d", __func__, ret);
142 *((int32_t *)param) = 1;
143 DacTesterPut(tester);
144 return HDF_ERR_IO;
145 }
146 }
147
148 *((int32_t *)param) = 1;
149 DacTesterPut(tester);
150 return val;
151 }
152
DacTestMultiThread(void)153 int32_t DacTestMultiThread(void)
154 {
155 int32_t ret;
156 uint32_t time;
157 struct OsalThread thread1, thread2;
158 struct OsalThreadParam cfg1, cfg2;
159 int32_t count1, count2;
160
161 count1 = 0;
162 count2 = 0;
163 time = 0;
164 ret = OsalThreadCreate(&thread1, (OsalThreadEntry)DacTestThreadFunc, (void *)&count1);
165 if (ret != HDF_SUCCESS) {
166 HDF_LOGE("create test thread1 fail:%d", ret);
167 return HDF_FAILURE;
168 }
169
170 ret = OsalThreadCreate(&thread2, (OsalThreadEntry)DacTestThreadFunc, (void *)&count2);
171 if (ret != HDF_SUCCESS) {
172 HDF_LOGE("create test thread1 fail:%d", ret);
173 return HDF_FAILURE;
174 }
175
176 cfg1.name = "DacTestThread-1";
177 cfg2.name = "DacTestThread-2";
178 cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
179 cfg1.stackSize = cfg2.stackSize = DAC_TEST_STACK_SIZE;
180
181 ret = OsalThreadStart(&thread1, &cfg1);
182 if (ret != HDF_SUCCESS) {
183 HDF_LOGE("start test thread1 fail:%d", ret);
184 return HDF_FAILURE;
185 }
186
187 ret = OsalThreadStart(&thread2, &cfg2);
188 if (ret != HDF_SUCCESS) {
189 HDF_LOGE("start test thread2 fail:%d", ret);
190 return HDF_FAILURE;
191 }
192
193 while (count1 == 0 || count2 == 0) {
194 HDF_LOGE("waitting testing thread finish...");
195 OsalMSleep(DAC_TEST_WAIT_TIMES);
196 time++;
197 if (time > DAC_TEST_WAIT_TIMEOUT) {
198 break;
199 }
200 }
201
202 (void)OsalThreadDestroy(&thread1);
203 (void)OsalThreadDestroy(&thread2);
204 return HDF_SUCCESS;
205 }
206
DacTestReliability(void)207 int32_t DacTestReliability(void)
208 {
209 struct DacTester *tester = NULL;
210 uint32_t val;
211
212 val = 0;
213 tester = DacTesterGet();
214 if (tester == NULL || tester->handle == NULL) {
215 return HDF_ERR_INVALID_OBJECT;
216 }
217 HDF_LOGD("%s: test dfr for DacRead ...", __func__);
218 // invalid handle
219 (void)DacWrite(NULL, tester->config.channel, val);
220 // invalid channel
221 (void)DacWrite(tester->handle, tester->config.maxChannel + 1, val);
222 DacTesterPut(tester);
223 return HDF_SUCCESS;
224 }
225
DacIfPerformanceTest(void)226 static int32_t DacIfPerformanceTest(void)
227 {
228 #ifdef __LITEOS__
229 // liteos the accuracy of the obtained time is too large and inaccurate.
230 return HDF_SUCCESS;
231 #endif
232
233 uint64_t startMs;
234 uint64_t endMs;
235 uint64_t useTime; // ms
236 struct DacTester *tester = NULL;
237 int32_t ret;
238 uint32_t val;
239
240 val = 0;
241 tester = DacTesterGet();
242 if (tester == NULL || tester->handle == NULL) {
243 HDF_LOGE("%s: get tester failed", __func__);
244 return HDF_ERR_INVALID_OBJECT;
245 }
246
247 startMs = OsalGetSysTimeMs();
248 ret = DacWrite(tester->handle, tester->config.channel, val);
249 if (ret != HDF_SUCCESS) {
250 HDF_LOGE("%s: write value failed:%u, ret:%d", __func__, val, ret);
251 DacTesterPut(tester);
252 return HDF_ERR_IO;
253 }
254 endMs = OsalGetSysTimeMs();
255
256 useTime = endMs - startMs;
257 HDF_LOGI("----->interface performance test:[start:%lld(ms) - end:%lld(ms) = %lld (ms)] < 1ms[%d]\r\n",
258 startMs, endMs, useTime, useTime < 1 ? true : false);
259 DacTesterPut(tester);
260 return HDF_SUCCESS;
261 }
262
263 struct DacTestEntry {
264 int cmd;
265 int32_t (*func)(void);
266 const char *name;
267 };
268 static struct DacTestEntry g_entry[] = {
269 { DAC_TEST_CMD_WRITE, DacTestWrite, "DacTestWrite" },
270 { DAC_TEST_CMD_MULTI_THREAD, DacTestMultiThread, "DacTestMultiThread" },
271 { DAC_TEST_CMD_RELIABILITY, DacTestReliability, "DacTestReliability" },
272 { DAC_TEST_CMD_IF_PERFORMANCE, DacIfPerformanceTest, "DacIfPerformanceTest" },
273 };
274
DacTestExecute(int cmd)275 int32_t DacTestExecute(int cmd)
276 {
277 uint32_t i;
278 int32_t ret = HDF_ERR_NOT_SUPPORT;
279
280 if (cmd > DAC_TEST_CMD_MAX) {
281 HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
282 ret = HDF_ERR_NOT_SUPPORT;
283 HDF_LOGE("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
284 return ret;
285 }
286
287 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
288 if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
289 continue;
290 }
291 ret = g_entry[i].func();
292 break;
293 }
294
295 HDF_LOGE("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
296 return ret;
297 }
298