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