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