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