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 "adc_test.h"
10 #include "adc_if.h"
11 #include "hdf_base.h"
12 #include "hdf_io_service_if.h"
13 #include "hdf_log.h"
14 #include "osal_mem.h"
15 #include "securec.h"
16 #include "osal_thread.h"
17 #include "osal_time.h"
18
19
20 #define HDF_LOG_TAG adc_test_c
21
22 #define TEST_ADC_VAL_NUM 50
23 #define ADC_TEST_WAIT_TIMES 100
24 #define ADC_TEST_WAIT_TIMEOUT 20
25 #define ADC_TEST_STACK_SIZE (1024 * 64)
26
AdcTestGetConfig(struct AdcTestConfig * config)27 static int32_t AdcTestGetConfig(struct AdcTestConfig *config)
28 {
29 int32_t ret;
30 struct HdfSBuf *reply = NULL;
31 struct HdfIoService *service = NULL;
32 const void *buf = NULL;
33 uint32_t len;
34
35 HDF_LOGD("%s: enter", __func__);
36 service = HdfIoServiceBind("ADC_TEST");
37 if (service == NULL) {
38 return HDF_ERR_NOT_SUPPORT;
39 }
40
41 do {
42 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
43 if (reply == NULL) {
44 HDF_LOGE("%s: failed to obtain reply", __func__);
45 ret = HDF_ERR_MALLOC_FAIL;
46 break;
47 }
48
49 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
50 if (ret != HDF_SUCCESS) {
51 HDF_LOGE("%s: remote dispatch failed", __func__);
52 break;
53 }
54
55 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
56 HDF_LOGE("%s: read buf failed", __func__);
57 ret = HDF_ERR_IO;
58 break;
59 }
60
61 if (len != sizeof(*config)) {
62 HDF_LOGE("%s: config size:%zu, read size:%u", __func__, sizeof(*config), len);
63 ret = HDF_ERR_IO;
64 break;
65 }
66
67 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
68 HDF_LOGE("%s: memcpy buf failed", __func__);
69 ret = HDF_ERR_IO;
70 break;
71 }
72 HDF_LOGD("%s: exit", __func__);
73 ret = HDF_SUCCESS;
74 } while (0);
75 HdfSbufRecycle(reply);
76 HdfIoServiceRecycle(service);
77 return ret;
78 }
79
AdcTesterGet(void)80 static struct AdcTester *AdcTesterGet(void)
81 {
82 int32_t ret;
83 static struct AdcTester tester;
84 static bool hasInit = false;
85
86 HDF_LOGE("%s: enter", __func__);
87 if (hasInit) {
88 return &tester;
89 }
90 ret = AdcTestGetConfig(&tester.config);
91 if (ret != HDF_SUCCESS) {
92 HDF_LOGE("%s: read config failed:%d", __func__, ret);
93 return NULL;
94 }
95 tester.handle = AdcOpen(tester.config.devNum);
96 if (tester.handle == NULL) {
97 HDF_LOGE("%s: open adc device:%u failed", __func__, tester.config.devNum);
98 return NULL;
99 }
100 hasInit = true;
101 HDF_LOGI("%s: done", __func__);
102 return &tester;
103 }
104
AdcTestRead(void)105 static int32_t AdcTestRead(void)
106 {
107 struct AdcTester *tester = NULL;
108 uint32_t value[TEST_ADC_VAL_NUM];
109 int32_t ret;
110 int i;
111
112 HDF_LOGI("%s: enter", __func__);
113 tester = AdcTesterGet();
114 if (tester == NULL) {
115 HDF_LOGE("%s: get tester failed", __func__);
116 return HDF_ERR_INVALID_OBJECT;
117 }
118 for (i = 0; i < TEST_ADC_VAL_NUM; i++) {
119 value[i] = 0;
120 ret = AdcRead(tester->handle, tester->config.channel, &value[i]);
121 if (ret != HDF_SUCCESS || value[i] >= (1U << tester->config.dataWidth)) {
122 HDF_LOGE("%s: read value failed, ret:%d", __func__, ret);
123 return HDF_ERR_IO;
124 }
125 }
126 HDF_LOGI("%s: ADC device num is %u", __func__, tester->config.devNum);
127
128 HDF_LOGI("%s: done", __func__);
129 return HDF_SUCCESS;
130 }
131
AdcTestThreadFunc(void * param)132 static int AdcTestThreadFunc(void *param)
133 {
134 struct AdcTester *tester = NULL;
135 uint32_t val;
136 int i;
137 int32_t ret;
138
139 HDF_LOGI("%s: enter", __func__);
140 tester = AdcTesterGet();
141 if (tester == NULL) {
142 HDF_LOGE("%s: get tester failed", __func__);
143 *((int32_t *)param) = 1;
144 return HDF_ERR_INVALID_OBJECT;
145 }
146
147 for (i = 0; i < ADC_TEST_WAIT_TIMES; i++) {
148 ret = AdcRead(tester->handle, tester->config.channel, &val);
149 if (ret != HDF_SUCCESS) {
150 HDF_LOGE("%s: AdcRead failed, ret:%d", __func__, ret);
151 *((int32_t *)param) = 1;
152 return HDF_ERR_IO;
153 }
154 }
155
156 *((int32_t *)param) = 1;
157 HDF_LOGI("%s: done", __func__);
158 return val;
159 }
160
AdcTestStartThread(struct OsalThread * thread1,struct OsalThread * thread2,const int32_t * count1,const int32_t * count2)161 static int32_t AdcTestStartThread(struct OsalThread *thread1, struct OsalThread *thread2,
162 const int32_t *count1, const int32_t *count2)
163 {
164 int32_t ret;
165 uint32_t time = 0;
166 struct OsalThreadParam cfg1;
167 struct OsalThreadParam cfg2;
168
169 if (memset_s(&cfg1, sizeof(cfg1), 0, sizeof(cfg1)) != EOK ||
170 memset_s(&cfg2, sizeof(cfg2), 0, sizeof(cfg2)) != EOK) {
171 HDF_LOGE("%s:memset_s failed.", __func__);
172 return HDF_ERR_IO;
173 }
174
175 cfg1.name = "AdcTestThread-1";
176 cfg2.name = "AdcTestThread-2";
177 cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
178 cfg1.stackSize = cfg2.stackSize = ADC_TEST_STACK_SIZE;
179
180 ret = OsalThreadStart(thread1, &cfg1);
181 if (ret != HDF_SUCCESS) {
182 HDF_LOGE("start test thread1 failed:%d", ret);
183 return ret;
184 }
185
186 ret = OsalThreadStart(thread2, &cfg2);
187 if (ret != HDF_SUCCESS) {
188 HDF_LOGE("start test thread2 failed:%d", ret);
189 }
190
191 while (*count1 == 0 || *count2 == 0) {
192 HDF_LOGV("waitting testing thread finish...");
193 OsalMSleep(ADC_TEST_WAIT_TIMES);
194 time++;
195 if (time > ADC_TEST_WAIT_TIMEOUT) {
196 break;
197 }
198 }
199 return ret;
200 }
201
AdcTestMultiThread(void)202 static int32_t AdcTestMultiThread(void)
203 {
204 int32_t ret;
205 struct OsalThread thread1;
206 struct OsalThread thread2;
207 int32_t count1 = 0;
208 int32_t count2 = 0;
209
210 ret = OsalThreadCreate(&thread1, (OsalThreadEntry)AdcTestThreadFunc, (void *)&count1);
211 if (ret != HDF_SUCCESS) {
212 HDF_LOGE("create test thread1 failed:%d", ret);
213 return ret;
214 }
215
216 ret = OsalThreadCreate(&thread2, (OsalThreadEntry)AdcTestThreadFunc, (void *)&count2);
217 if (ret != HDF_SUCCESS) {
218 (void)OsalThreadDestroy(&thread1);
219 HDF_LOGE("create test thread1 failed:%d", ret);
220 return ret;
221 }
222
223 ret = AdcTestStartThread(&thread1, &thread2, &count1, &count2);
224 if (ret != HDF_SUCCESS) {
225 HDF_LOGE("test start thread failed:%d", ret);
226 }
227
228 (void)OsalThreadDestroy(&thread1);
229 (void)OsalThreadDestroy(&thread2);
230 return ret;
231 }
232
AdcTestReliability(void)233 static int32_t AdcTestReliability(void)
234 {
235 struct AdcTester *tester = NULL;
236 uint32_t val;
237
238 HDF_LOGI("%s: enter", __func__);
239 tester = AdcTesterGet();
240 if (tester == NULL || tester->handle == NULL) {
241 return HDF_ERR_INVALID_OBJECT;
242 }
243 HDF_LOGD("%s: test dfr for AdcRead ...", __func__);
244 // invalid handle
245 (void)AdcRead(NULL, tester->config.channel, &val);
246 // invalid channel
247 (void)AdcRead(tester->handle, tester->config.maxChannel + 1, &val);
248 // invalid val pointer
249 (void)AdcRead(tester->handle, tester->config.channel, NULL);
250 HDF_LOGI("%s: done", __func__);
251 return HDF_SUCCESS;
252 }
253
AdcIfPerformanceTest(void)254 static int32_t AdcIfPerformanceTest(void)
255 {
256 #ifdef __LITEOS__
257 // liteos the accuracy of the obtained time is too large and inaccurate.
258 return HDF_SUCCESS;
259 #endif
260 struct AdcTester *tester = NULL;
261 uint64_t startMs;
262 uint64_t endMs;
263 uint64_t useTime; // ms
264 uint32_t val;
265 int32_t ret;
266
267 tester = AdcTesterGet();
268 if (tester == NULL || tester->handle == NULL) {
269 HDF_LOGE("%s:get tester fail", __func__);
270 return HDF_ERR_INVALID_OBJECT;
271 }
272
273 startMs = OsalGetSysTimeMs();
274 ret = AdcRead(tester->handle, tester->config.channel, &val);
275 if (ret == HDF_SUCCESS) {
276 endMs = OsalGetSysTimeMs();
277 useTime = endMs - startMs;
278 HDF_LOGI("----->interface performance test:[start - end] < 1ms[%s]\r\n", useTime < 1 ? "yes" : "no");
279 return HDF_SUCCESS;
280 }
281 return HDF_FAILURE;
282 }
283
284 struct AdcTestEntry {
285 int cmd;
286 int32_t (*func)(void);
287 const char *name;
288 };
289
290 static struct AdcTestEntry g_entry[] = {
291 { ADC_TEST_CMD_READ, AdcTestRead, "AdcTestRead" },
292 { ADC_TEST_CMD_MULTI_THREAD, AdcTestMultiThread, "AdcTestMultiThread" },
293 { ADC_TEST_CMD_RELIABILITY, AdcTestReliability, "AdcTestReliability" },
294 { ADC_IF_PERFORMANCE_TEST, AdcIfPerformanceTest, "AdcIfPerformanceTest" },
295 };
296
AdcTestExecute(int cmd)297 int32_t AdcTestExecute(int cmd)
298 {
299 uint32_t i;
300 int32_t ret = HDF_ERR_NOT_SUPPORT;
301
302 if (cmd > ADC_TEST_CMD_MAX) {
303 HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
304 ret = HDF_ERR_NOT_SUPPORT;
305 HDF_LOGE("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
306 return ret;
307 }
308
309 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
310 if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
311 continue;
312 }
313 ret = g_entry[i].func();
314 break;
315 }
316
317 HDF_LOGE("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
318 return ret;
319 }
320