1 /*
2 * Copyright (c) 2020-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 "i2c_test.h"
10 #include "hdf_base.h"
11 #include "hdf_io_service_if.h"
12 #include "hdf_log.h"
13 #include "i2c_if.h"
14 #include "osal_mem.h"
15 #include "osal_thread.h"
16 #include "osal_time.h"
17 #include "securec.h"
18
19 #define HDF_LOG_TAG i2c_test
20
21 #define I2C_TEST_8BIT 8
22 #define I2C_TEST_MSG_NUM 2
23 #define I2C_TEST_BUF_SIZE_MAX 128
24 #define I2C_TEST_REG_LEN 2
25 #define I2C_TEST_MLTTHD_TIMES 1000
26 #define I2C_TEST_STACK_SIZE (1024 * 100)
27 #define I2C_TEST_WAIT_TIMES 200
28
29 static struct I2cMsg g_msgs[I2C_TEST_MSG_NUM];
30 static uint8_t *g_buf;
31 static uint8_t g_regs[I2C_TEST_REG_LEN];
32
I2cTestGetConfig(struct I2cTestConfig * config)33 static int32_t I2cTestGetConfig(struct I2cTestConfig *config)
34 {
35 int32_t ret;
36 struct HdfSBuf *reply = NULL;
37 struct HdfIoService *service = NULL;
38 const void *buf = NULL;
39 uint32_t len;
40
41 HDF_LOGD("I2cTestGetConfig: enter!");
42 service = HdfIoServiceBind("I2C_TEST");
43 if (service == NULL) {
44 return HDF_ERR_NOT_SUPPORT;
45 }
46
47 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
48 if (reply == NULL) {
49 HDF_LOGE("I2cTestGetConfig: failed to obtain reply!");
50 return HDF_ERR_MALLOC_FAIL;
51 }
52
53 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
54 if (ret != HDF_SUCCESS) {
55 HDF_LOGE("I2cTestGetConfig: remote dispatch fail:%d", ret);
56 ret = HDF_ERR_IO;
57 goto EXIT;
58 }
59
60 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
61 HDF_LOGE("I2cTestGetConfig: read buf fail!");
62 ret = HDF_ERR_IO;
63 goto EXIT;
64 }
65
66 if (len != sizeof(*config)) {
67 HDF_LOGE("I2cTestGetConfig: config size:%u, but read size:%u!", sizeof(*config), len);
68 ret = HDF_ERR_IO;
69 goto EXIT;
70 }
71
72 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
73 HDF_LOGE("I2cTestGetConfig: memcpy buf fail!");
74 ret = HDF_ERR_IO;
75 goto EXIT;
76 }
77 ret = HDF_SUCCESS;
78 EXIT:
79 HdfSbufRecycle(reply);
80 HDF_LOGD("I2cTestGetConfig: exit!");
81 HdfIoServiceRecycle(service);
82 return ret;
83 }
84
I2cTesterGet(void)85 struct I2cTester *I2cTesterGet(void)
86 {
87 int32_t ret;
88 static struct I2cTester tester;
89 static bool hasInit = false;
90
91 if (hasInit) {
92 return &tester;
93 }
94
95 ret = I2cTestGetConfig(&tester.config);
96 if (ret != HDF_SUCCESS) {
97 HDF_LOGE("I2cTesterGet: read config fail:%d", ret);
98 return NULL;
99 }
100
101 tester.handle = I2cOpen(tester.config.busNum);
102 if (tester.handle == NULL) {
103 HDF_LOGE("I2cTesterGet: open i2cBus:%u fail!", tester.config.busNum);
104 return NULL;
105 }
106
107 hasInit = true;
108 return &tester;
109 }
110
I2cTestMallocBuf(struct I2cTester * tester)111 static int32_t I2cTestMallocBuf(struct I2cTester *tester)
112 {
113 struct I2cTestConfig *config = &tester->config;
114
115 if (g_buf == NULL) {
116 g_buf = OsalMemCalloc(config->bufSize);
117 if (g_buf == NULL) {
118 HDF_LOGE("I2cTestMallocBuf: malloc buf fail!");
119 return HDF_ERR_MALLOC_FAIL;
120 }
121 }
122
123 g_regs[0] = (uint8_t)config->regAddr;
124 if (config->regLen > 1) {
125 g_regs[1] = g_regs[0];
126 g_regs[0] = (uint8_t)(config->regAddr >> I2C_TEST_8BIT);
127 }
128
129 g_msgs[0].addr = config->devAddr;
130 g_msgs[0].flags = 0;
131 g_msgs[0].len = config->regLen;
132 g_msgs[0].buf = g_regs;
133
134 g_msgs[1].addr = config->devAddr;
135 g_msgs[1].flags = I2C_FLAG_READ;
136 g_msgs[1].len = config->bufSize;
137 g_msgs[1].buf = g_buf;
138
139 return HDF_SUCCESS;
140 }
141
I2cTestSetUpAll(void)142 int32_t I2cTestSetUpAll(void)
143 {
144 struct I2cTester *tester = NULL;
145 struct I2cTestConfig *cfg = NULL;
146
147 HDF_LOGD("I2cTestSetUpAll: enter!");
148 tester = I2cTesterGet();
149 if (tester == NULL) {
150 HDF_LOGE("I2cTestSetUpAll: get tester fail!");
151 return HDF_ERR_INVALID_OBJECT;
152 }
153 tester->total = I2C_TEST_CMD_MAX;
154 tester->fails = 0;
155
156 cfg = &tester->config;
157 HDF_LOGE("I2cTestSetUpAll: test on bus:0x%x, addr:0x%x, reg:0x%x, reglen:0x%x, size:0x%x",
158 cfg->busNum, cfg->devAddr, cfg->regAddr, cfg->regLen, cfg->bufSize);
159 if (I2cTestMallocBuf(tester) != HDF_SUCCESS) {
160 HDF_LOGE("I2cTestSetUpAll: set up test case fail!");
161 }
162 HDF_LOGD("I2cTestSetUpAll: exit!");
163 return HDF_SUCCESS;
164 }
165
I2cTestTearDownAll(void)166 int32_t I2cTestTearDownAll(void)
167 {
168 if (g_buf != NULL) {
169 OsalMemFree(g_buf);
170 g_buf = NULL;
171 }
172
173 return HDF_SUCCESS;
174 }
175
I2cTestSetUpSingle(void)176 int32_t I2cTestSetUpSingle(void)
177 {
178 return HDF_SUCCESS;
179 }
180
I2cTestTearDownSingle(void)181 int32_t I2cTestTearDownSingle(void)
182 {
183 return HDF_SUCCESS;
184 }
185
I2cTestTransfer(void)186 int32_t I2cTestTransfer(void)
187 {
188 int32_t ret;
189 struct I2cTester *tester = NULL;
190
191 tester = I2cTesterGet();
192 if (tester == NULL || tester->handle == NULL) {
193 return HDF_ERR_INVALID_OBJECT;
194 }
195
196 /* transfer one write msg */
197 ret = I2cTransfer(tester->handle, g_msgs, 1);
198 if (ret != 1) {
199 HDF_LOGE("I2cTestTransfer: I2cTransfer(write) err:%d", ret);
200 return HDF_FAILURE;
201 }
202
203 /* transfer one read msg */
204 ret = I2cTransfer(tester->handle, g_msgs + 1, 1);
205 if (ret != 1) {
206 HDF_LOGE("I2cTestTransfer: I2cTransfer(read) err:%d", ret);
207 return HDF_FAILURE;
208 }
209
210 /* transfer two msgs including a read msg and a write msg */
211 ret = I2cTransfer(tester->handle, g_msgs, I2C_TEST_MSG_NUM);
212 if (ret != I2C_TEST_MSG_NUM) {
213 HDF_LOGE("I2cTestTransfer: I2cTransfer(mix) err:%d", ret);
214 return HDF_FAILURE;
215 }
216 return HDF_SUCCESS;
217 }
218
I2cTestWriteRead(void)219 int32_t I2cTestWriteRead(void)
220 {
221 return HDF_SUCCESS;
222 }
223
I2cTestThreadFunc(void * param)224 static int I2cTestThreadFunc(void *param)
225 {
226 int32_t i, ret;
227 struct I2cTester *tester = NULL;
228
229 tester = I2cTesterGet();
230 if (tester == NULL || tester->handle == NULL) {
231 *((int32_t *)param) = 1;
232 return HDF_ERR_INVALID_OBJECT;
233 }
234
235 for (i = 0; i < I2C_TEST_MLTTHD_TIMES; i++) {
236 ret = I2cTransfer(tester->handle, g_msgs, I2C_TEST_MSG_NUM);
237 if (ret != I2C_TEST_MSG_NUM) {
238 #ifdef __USER__
239 HDF_LOGE("I2cTransfer-user err in multithread test:%d", ret);
240 #else
241 HDF_LOGE("I2cTransfer-kerl err in multithread test:%d", ret);
242 #endif
243 }
244 }
245
246 *((int32_t *)param) = 1;
247 return HDF_SUCCESS;
248 }
249
I2cTestMultiThread(void)250 int32_t I2cTestMultiThread(void)
251 {
252 int32_t ret;
253 struct OsalThread thread1, thread2;
254 struct OsalThreadParam cfg1, cfg2;
255 int32_t count1, count2;
256
257 count1 = count2 = 0;
258
259 ret = OsalThreadCreate(&thread1, (OsalThreadEntry)I2cTestThreadFunc, (void *)&count1);
260 if (ret != HDF_SUCCESS) {
261 HDF_LOGE("create test thread1 fail:%d", ret);
262 return HDF_FAILURE;
263 }
264
265 ret = OsalThreadCreate(&thread2, (OsalThreadEntry)I2cTestThreadFunc, (void *)&count2);
266 if (ret != HDF_SUCCESS) {
267 (void)OsalThreadDestroy(&thread1);
268 HDF_LOGE("create test thread1 fail:%d", ret);
269 return HDF_FAILURE;
270 }
271
272 cfg1.name = "I2cTestThread-1";
273 cfg2.name = "I2cTestThread-2";
274 cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
275 cfg1.stackSize = cfg2.stackSize = I2C_TEST_STACK_SIZE;
276
277 ret = OsalThreadStart(&thread1, &cfg1);
278 if (ret != HDF_SUCCESS) {
279 (void)OsalThreadDestroy(&thread1);
280 (void)OsalThreadDestroy(&thread2);
281 HDF_LOGE("start test thread1 fail:%d", ret);
282 return HDF_FAILURE;
283 }
284
285 ret = OsalThreadStart(&thread2, &cfg2);
286 if (ret != HDF_SUCCESS) {
287 (void)OsalThreadDestroy(&thread1);
288 (void)OsalThreadDestroy(&thread2);
289 HDF_LOGE("start test thread2 fail:%d", ret);
290 return HDF_FAILURE;
291 }
292
293 while (count1 == 0 || count2 == 0) {
294 HDF_LOGE("waitting testing thread finish...");
295 OsalMSleep(I2C_TEST_WAIT_TIMES);
296 }
297
298 (void)OsalThreadDestroy(&thread1);
299 (void)OsalThreadDestroy(&thread2);
300 return HDF_SUCCESS;
301 }
302
I2cTestReliability(void)303 int32_t I2cTestReliability(void)
304 {
305 struct I2cTester *tester = NULL;
306
307 HDF_LOGD("I2cTestReliability: test dfr for I2cTransfer ...");
308 tester = I2cTesterGet();
309 if (tester == NULL || tester->handle == NULL) {
310 return HDF_ERR_INVALID_OBJECT;
311 }
312 /* invalid device handle */
313 (void)I2cTransfer(NULL, g_msgs, I2C_TEST_MSG_NUM);
314 /* invalid device msgs */
315 (void)I2cTransfer(tester->handle, NULL, I2C_TEST_MSG_NUM);
316 /* invalid device msg number */
317 (void)I2cTransfer(tester->handle, g_msgs, -1);
318
319 return HDF_SUCCESS;
320 }
321
I2cTestPeformance(void)322 int32_t I2cTestPeformance(void)
323 {
324 #ifdef __LITEOS__
325 // liteos the accuracy of the obtained time is too large and inaccurate.
326 return HDF_SUCCESS;
327 #endif
328 uint64_t startMs;
329 uint64_t endMs;
330 uint64_t useTime; // ms
331 struct I2cTester *tester = NULL;
332 DevHandle handle = NULL;
333
334 tester = I2cTesterGet();
335 if (tester == NULL || tester->handle == NULL) {
336 HDF_LOGE("%s:get tester fail", __func__);
337 return HDF_ERR_INVALID_OBJECT;
338 }
339
340 startMs = OsalGetSysTimeMs();
341 handle = I2cOpen(tester->config.busNum);
342 endMs = OsalGetSysTimeMs();
343
344 if (handle != NULL) {
345 useTime = endMs - startMs;
346 HDF_LOGI("----->interface performance test:[start:%lld(ms) - end:%lld(ms) = %lld (ms)] < 1ms[%d]\r\n",
347 startMs, endMs, useTime, useTime < 1 ? true : false);
348 I2cClose(handle);
349 return HDF_SUCCESS;
350 }
351
352 return HDF_FAILURE;
353 }
354
355 struct I2cTestEntry {
356 int cmd;
357 int32_t (*func)(void);
358 const char *name;
359 };
360
361 static struct I2cTestEntry g_entry[] = {
362 { I2C_TEST_CMD_TRANSFER, I2cTestTransfer, "I2cTestTransfer" },
363 { I2C_TEST_CMD_WRITE_READ, I2cTestWriteRead, "I2cTestWriteRead" },
364 { I2C_TEST_CMD_MULTI_THREAD, I2cTestMultiThread, "I2cTestMultiThread" },
365 { I2C_TEST_CMD_RELIABILITY, I2cTestReliability, "I2cTestReliability" },
366 { I2C_TEST_CMD_PERFORMANCE, I2cTestPeformance, "I2cTestPeformance" },
367 { I2C_TEST_CMD_SETUP_ALL, I2cTestSetUpAll, "I2cTestSetUpAll" },
368 { I2C_TEST_CMD_TEARDOWN_ALL, I2cTestTearDownAll, "I2cTestTearDownAll" },
369 { I2C_TEST_CMD_SETUP_SINGLE, I2cTestSetUpSingle, "I2cTestSetUpSingle" },
370 { I2C_TEST_CMD_TEARDOWN_SINGLE, I2cTestTearDownSingle, "I2cTestTearDownSingle" },
371 };
372
I2cTestExecute(int cmd)373 int32_t I2cTestExecute(int cmd)
374 {
375 uint32_t i;
376 int32_t ret = HDF_ERR_NOT_SUPPORT;
377
378 if (cmd > I2C_TEST_CMD_MAX) {
379 HDF_LOGE("I2cTestExecute: invalid cmd:%d", cmd);
380 ret = HDF_ERR_NOT_SUPPORT;
381 HDF_LOGE("[I2cTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
382 return ret;
383 }
384
385 for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
386 if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
387 continue;
388 }
389 ret = g_entry[i].func();
390 break;
391 }
392
393 HDF_LOGE("[I2cTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
394 return ret;
395 }
396
I2cTestExecuteAll(void)397 void I2cTestExecuteAll(void)
398 {
399 int32_t i;
400 int32_t ret;
401 int32_t fails = 0;
402
403 /* setup env for all test cases */
404 (void)I2cTestExecute(I2C_TEST_CMD_SETUP_ALL);
405
406 for (i = 0; i <= I2C_TEST_CMD_RELIABILITY; i++) {
407 ret = I2cTestExecute(i);
408 fails += (ret != HDF_SUCCESS) ? 1 : 0;
409 }
410
411 /* teardown env for all test cases */
412 (void)I2cTestExecute(I2C_TEST_CMD_TEARDOWN_ALL);
413
414 HDF_LOGE("I2cTestExecuteALL: **********PASS:%d FAIL:%d************\n\n",
415 I2C_TEST_CMD_RELIABILITY + 1 - fails, fails);
416 }
417