• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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