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