• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "i3c_test.h"
10 #include "hdf_base.h"
11 #include "hdf_io_service_if.h"
12 #include "hdf_log.h"
13 #include "i3c_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 i3c_test_c
20 
21 #define I3C_TEST_MSG_NUM           2
22 #define I3C_TEST_8BIT              8
23 #define I3C_TEST_WAIT_TIMES        100
24 #define I3C_TEST_WAIT_TIMEOUT      20
25 #define I3C_TEST_STACK_SIZE        (1024 * 256)
26 #define I3C_TEST_IBI_PAYLOAD       16
27 #define I3C_TEST_REG_LEN           2
28 
29 static struct I3cMsg g_msgs[I3C_TEST_MSG_NUM];
30 static uint8_t *g_buf;
31 static uint8_t g_regs[I3C_TEST_REG_LEN];
32 
33 struct I3cTestEntry {
34     int cmd;
35     int32_t (*func)(void *param);
36     const char *name;
37 };
38 
I3cTestGetTestConfig(struct I3cTestConfig * config)39 static int32_t I3cTestGetTestConfig(struct I3cTestConfig *config)
40 {
41     int32_t ret;
42     struct HdfSBuf *reply = NULL;
43     struct HdfIoService *service = NULL;
44     const void *buf = NULL;
45     uint32_t len;
46 
47     service = HdfIoServiceBind("I3C_TEST");
48     if (service == NULL) {
49         return HDF_ERR_NOT_SUPPORT;
50     }
51 
52     reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
53     if (reply == NULL) {
54         HDF_LOGE("%s: Failed to obtain reply", __func__);
55         return HDF_ERR_MALLOC_FAIL;
56     }
57 
58     ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
59     if (ret != HDF_SUCCESS) {
60         HDF_LOGE("%s: Remote dispatch failed", __func__);
61         return ret;
62     }
63 
64     if (!HdfSbufReadBuffer(reply, &buf, &len)) {
65         HDF_LOGE("%s: Read buf failed", __func__);
66         HdfSbufRecycle(reply);
67         return HDF_ERR_IO;
68     }
69 
70     if (len != sizeof(*config)) {
71         HDF_LOGE("%s: Config size:%zu, read size:%u", __func__, sizeof(*config), len);
72         HdfSbufRecycle(reply);
73         return HDF_ERR_IO;
74     }
75 
76     if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
77         HDF_LOGE("%s: Memcpy buf failed", __func__);
78         HdfSbufRecycle(reply);
79         return HDF_ERR_IO;
80     }
81     HdfSbufRecycle(reply);
82     HDF_LOGD("%s: Done", __func__);
83     return HDF_SUCCESS;
84 }
85 
I3cTesterGet(void)86 struct I3cTester *I3cTesterGet(void)
87 {
88     int32_t ret;
89     static struct I3cTester tester;
90     static bool hasInit = false;
91 
92     if (hasInit) {
93         return &tester;
94     }
95     ret = I3cTestGetTestConfig(&tester.config);
96     if (ret != HDF_SUCCESS) {
97         HDF_LOGE("%s: read config failed, ret = %d", __func__, ret);
98         return NULL;
99     }
100     tester.handle = I3cOpen(tester.config.busId);
101     if (tester.handle == NULL) {
102         HDF_LOGE("%s: Open I3C controller: %u failed!", __func__, tester.config.busId);
103         return NULL;
104     }
105     hasInit = true;
106     HDF_LOGD("%s: Done", __func__);
107     return &tester;
108 }
109 
I3cTestMallocBuf(struct I3cTester * tester)110 static int32_t I3cTestMallocBuf(struct I3cTester *tester)
111 {
112     struct I3cTestConfig *config = &tester->config;
113 
114     if (g_buf == NULL) {
115         g_buf = OsalMemCalloc(config->bufSize);
116         if (g_buf == NULL) {
117             HDF_LOGE("I3cTestMallocBuf: malloc buf fail!");
118             return HDF_ERR_MALLOC_FAIL;
119         }
120     }
121 
122     g_regs[0] = (uint8_t)config->regAddr;
123     if (config->regLen > 1) {
124         g_regs[1] = g_regs[0];
125         g_regs[0] = (uint8_t)(config->regAddr >> I3C_TEST_8BIT);
126     }
127 
128     g_msgs[0].addr = config->devAddr;
129     g_msgs[0].flags = 0;
130     g_msgs[0].len = config->regLen;
131     g_msgs[0].buf = g_regs;
132 
133     g_msgs[1].addr = config->devAddr;
134     g_msgs[1].flags = I3C_FLAG_READ;
135     g_msgs[1].len = config->bufSize;
136     g_msgs[1].buf = g_buf;
137 
138     return HDF_SUCCESS;
139 }
140 
I3cTestSetUpAll(void * param)141 int32_t I3cTestSetUpAll(void *param)
142 {
143     struct I3cTester *tester = NULL;
144     struct I3cTestConfig *cfg = NULL;
145 
146     (void) param;
147     HDF_LOGD("I3cTestSetUpAll: enter!");
148     tester = I3cTesterGet();
149     if (tester == NULL) {
150         HDF_LOGE("I3cTestSetUpAll: get tester fail!");
151         return HDF_ERR_INVALID_OBJECT;
152     }
153     tester->total = I3C_TEST_CMD_MAX;
154     tester->fails = 0;
155 
156     cfg = &tester->config;
157     HDF_LOGD("I3cTestSetUpAll: test on bus:0x%x, addr:0x%x, reg:0x%x, reglen:0x%x, size:0x%x",
158         cfg->busId, cfg->devAddr, cfg->regAddr, cfg->regLen, cfg->bufSize);
159     if (I3cTestMallocBuf(tester) != HDF_SUCCESS) {
160         HDF_LOGE("I3cTestSetUpAll: set up test case fail!");
161     }
162     HDF_LOGD("I3cTestSetUpAll: exit!");
163     *((int32_t *)param) = 1;
164 
165     return HDF_SUCCESS;
166 }
167 
I3cTestTearDownAll(void * param)168 int32_t I3cTestTearDownAll(void *param)
169 {
170     if (g_buf != NULL) {
171         OsalMemFree(g_buf);
172         g_buf = NULL;
173     }
174     *((int32_t *)param) = 1;
175 
176     return HDF_SUCCESS;
177 }
178 
I3cTestSetUpSingle(void)179 int32_t I3cTestSetUpSingle(void)
180 {
181     return HDF_SUCCESS;
182 }
183 
I3cTestTearDownSingle(void)184 int32_t I3cTestTearDownSingle(void)
185 {
186     return HDF_SUCCESS;
187 }
188 
I3cTestTransfer(void * param)189 int32_t I3cTestTransfer(void *param)
190 {
191     struct I3cTester *tester = NULL;
192     int32_t ret;
193 
194     tester = I3cTesterGet();
195     if (tester == NULL) {
196         HDF_LOGE("%s: Get tester failed!", __func__);
197         *((int32_t *)param) = 1;
198         return HDF_ERR_INVALID_OBJECT;
199     }
200     /* transfer one write msg */
201     ret = I3cTransfer(tester->handle, g_msgs, 1, I3C_MODE);
202     if (ret != 1) {
203         HDF_LOGE("%s: I3cTransfer(write) err: %d", __func__, ret);
204         *((int32_t *)param) = 1;
205         return HDF_FAILURE;
206     }
207 
208     /* transfer one read msg */
209     ret = I3cTransfer(tester->handle, g_msgs + 1, 1, I3C_MODE);
210     if (ret != 1) {
211         HDF_LOGE("%s: I3cTransfer(read) err: %d", __func__, ret);
212         *((int32_t *)param) = 1;
213         return HDF_FAILURE;
214     }
215 
216     /* transfer two msgs including a read msg and a write msg */
217     ret = I3cTransfer(tester->handle, g_msgs, I3C_TEST_MSG_NUM, I3C_MODE);
218     if (ret != I3C_TEST_MSG_NUM) {
219         HDF_LOGE("%s: I3cTransfer(mix) err: %d", __func__, ret);
220         *((int32_t *)param) = 1;
221         return HDF_FAILURE;
222     }
223     *((int32_t *)param) = 1;
224     HDF_LOGD("%s: Done", __func__);
225     return HDF_SUCCESS;
226 }
227 
I3cTestSetConfig(void * param)228 int32_t I3cTestSetConfig(void *param)
229 {
230     struct I3cTester *tester = NULL;
231     struct I3cConfig *config = NULL;
232     int32_t ret;
233 
234     tester = I3cTesterGet();
235     if (tester == NULL) {
236         HDF_LOGE("%s: Get tester failed!", __func__);
237         *((int32_t *)param) = 1;
238         return HDF_ERR_INVALID_OBJECT;
239     }
240 
241     config = (struct I3cConfig*)OsalMemCalloc(sizeof(*config));
242     if (config == NULL) {
243         HDF_LOGE("%s: MemCalloc failed!", __func__);
244         *((int32_t *)param) = 1;
245         return HDF_ERR_MALLOC_FAIL;
246     }
247 
248     config->busMode = I3C_BUS_HDR_MODE;
249     config->curMaster = NULL;
250     ret = I3cSetConfig(tester->handle, config);
251     if (ret != HDF_SUCCESS) {
252         HDF_LOGE("%s: Set config failed!, busId = %d", __func__, tester->config.busId);
253         OsalMemFree(config);
254         *((int32_t *)param) = 1;
255         return HDF_FAILURE;
256     }
257     OsalMemFree(config);
258     config = NULL;
259     HDF_LOGD("%s: Done", __func__);
260     *((int32_t *)param) = 1;
261 
262     return HDF_SUCCESS;
263 }
264 
I3cTestGetConfig(void * param)265 int32_t I3cTestGetConfig(void *param)
266 {
267     struct I3cTester *tester = NULL;
268     struct I3cConfig *config = NULL;
269     int32_t ret;
270 
271     tester = I3cTesterGet();
272     if (tester == NULL) {
273         HDF_LOGE("%s: Get tester failed!", __func__);
274         *((int32_t *)param) = 1;
275         return HDF_ERR_INVALID_OBJECT;
276     }
277 
278     config = (struct I3cConfig*)OsalMemCalloc(sizeof(*config));
279     if (config == NULL) {
280         HDF_LOGE("%s: MemCalloc failed!", __func__);
281         *((int32_t *)param) = 1;
282         return HDF_ERR_MALLOC_FAIL;
283     }
284 
285     ret = I3cGetConfig(tester->handle, config);
286     if (ret != HDF_SUCCESS) {
287         HDF_LOGE("%s: Get config failed!, busId = %d", __func__, tester->config.busId);
288         OsalMemFree(config);
289         *((int32_t *)param) = 1;
290         return HDF_FAILURE;
291     }
292 
293     OsalMemFree(config);
294     config = NULL;
295     *((int32_t *)param) = 1;
296     HDF_LOGD("%s: Done", __func__);
297 
298     return HDF_SUCCESS;
299 }
300 
TestI3cIbiFunc(DevHandle handle,uint16_t addr,struct I3cIbiData data)301 static int32_t TestI3cIbiFunc(DevHandle handle, uint16_t addr, struct I3cIbiData data)
302 {
303     (void)handle;
304     (void)addr;
305     HDF_LOGD("%s: %.16s", __func__, (char *)data.buf);
306 
307     return HDF_SUCCESS;
308 }
309 
I3cTestRequestIbi(void * param)310 int32_t I3cTestRequestIbi(void *param)
311 {
312     struct I3cTester *tester = NULL;
313     int32_t ret;
314 
315     tester = I3cTesterGet();
316     if (tester == NULL) {
317         HDF_LOGE("%s: Get tester failed!", __func__);
318         *((int32_t *)param) = 1;
319         return HDF_ERR_INVALID_OBJECT;
320     }
321 
322     ret = I3cRequestIbi(tester->handle, tester->config.devAddr, TestI3cIbiFunc, I3C_TEST_IBI_PAYLOAD);
323     if (ret != HDF_SUCCESS) {
324         *((int32_t *)param) = 1;
325         HDF_LOGE("%s: Requset IBI failed!, busId = %d", __func__, tester->config.busId);
326         return HDF_FAILURE;
327     }
328     *((int32_t *)param) = 1;
329     HDF_LOGD("%s: Done", __func__);
330 
331     return HDF_SUCCESS;
332 }
333 
I3cTestFreeIbi(void * param)334 int32_t I3cTestFreeIbi(void *param)
335 {
336     struct I3cTester *tester = NULL;
337     int32_t ret;
338 
339     tester = I3cTesterGet();
340     if (tester == NULL) {
341         HDF_LOGE("%s: Get tester failed!", __func__);
342         return HDF_ERR_INVALID_OBJECT;
343     }
344 
345     ret = I3cFreeIbi(tester->handle, tester->config.devAddr);
346     if (ret != HDF_SUCCESS) {
347         HDF_LOGE("%s: Free IBI failed!, busId = %d", __func__, tester->config.busId);
348         *((int32_t *)param) = 1;
349         return HDF_FAILURE;
350     }
351     *((int32_t *)param) = 1;
352     HDF_LOGD("%s: done", __func__);
353 
354     return HDF_SUCCESS;
355 }
356 
I3cTestThreadFunc(OsalThreadEntry func)357 int32_t I3cTestThreadFunc(OsalThreadEntry func)
358 {
359     int32_t ret;
360     uint32_t time;
361     struct OsalThread thread1, thread2;
362     struct OsalThreadParam cfg1, cfg2;
363     int32_t count1, count2;
364 
365     count1 = count2 = 0;
366     time = 0;
367     ret = OsalThreadCreate(&thread1, func, (void *)&count1);
368     if (ret != HDF_SUCCESS) {
369         HDF_LOGE("create test thread1 fail:%d", ret);
370         return HDF_FAILURE;
371     }
372 
373     ret = OsalThreadCreate(&thread2, func, (void *)&count2);
374     if (ret != HDF_SUCCESS) {
375         HDF_LOGE("create test thread1 fail:%d", ret);
376         return HDF_FAILURE;
377     }
378 
379     cfg1.name = "I3cTestThread-1";
380     cfg2.name = "I3cTestThread-2";
381     cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
382     cfg1.stackSize = cfg2.stackSize = I3C_TEST_STACK_SIZE;
383 
384     ret = OsalThreadStart(&thread1, &cfg1);
385     if (ret != HDF_SUCCESS) {
386         HDF_LOGE("start test thread1 fail:%d", ret);
387         return HDF_FAILURE;
388     }
389 
390     ret = OsalThreadStart(&thread2, &cfg2);
391     if (ret != HDF_SUCCESS) {
392         HDF_LOGE("start test thread2 fail:%d", ret);
393         return HDF_FAILURE;
394     }
395 
396     while (count1 == 0 || count2 == 0) {
397         HDF_LOGE("waitting testing thread finish...");
398         OsalMSleep(I3C_TEST_WAIT_TIMES);
399         time++;
400         if (time > I3C_TEST_WAIT_TIMEOUT) {
401             break;
402         }
403     }
404 
405     (void)OsalThreadDestroy(&thread1);
406     (void)OsalThreadDestroy(&thread2);
407     HDF_LOGD("%s: done", __func__);
408 
409     return HDF_SUCCESS;
410 }
411 
412 static struct I3cTestEntry g_multiThreadEntry[] = {
413     { I3C_TEST_CMD_TRANSFER, I3cTestTransfer, "I3cTestTransfer" },
414     { I3C_TEST_CMD_SET_CONFIG, I3cTestSetConfig, "I3cTestSetConfig" },
415     { I3C_TEST_CMD_GET_CONFIG, I3cTestGetConfig, "I3cTestGetConfig" },
416     { I3C_TEST_CMD_REQUEST_IBI, I3cTestRequestIbi, "I3cTestRequestIbi" },
417     { I3C_TEST_CMD_FREE_IBI, I3cTestFreeIbi, "I3cTestFreeIbi" },
418 };
419 
I3cTestMultiThread(void * param)420 int32_t I3cTestMultiThread(void *param)
421 {
422     uint32_t i;
423     int32_t ret;
424 
425     for (i = 0; i < sizeof(g_multiThreadEntry) / sizeof(g_multiThreadEntry[0]); i++) {
426         if (g_multiThreadEntry[i].func == NULL) {
427             HDF_LOGE("%s: func is NULL", __func__);
428             return HDF_FAILURE;
429         }
430         HDF_LOGI("%s: =================calling func %d =========================", __func__, i);
431         ret = I3cTestThreadFunc((OsalThreadEntry)g_multiThreadEntry[i].func);
432         if (ret != HDF_SUCCESS) {
433             HDF_LOGE("%s: Multithreading test failed: %u", __func__, i);
434             return ret;
435         }
436     }
437     *((int32_t *)param) = 1;
438 
439     return HDF_SUCCESS;
440 }
441 
I3cTestReliability(void * param)442 int32_t I3cTestReliability(void *param)
443 {
444     struct I3cTester *tester = NULL;
445     struct I3cConfig *config = NULL;
446 
447     tester = I3cTesterGet();
448     if (tester == NULL || tester->handle == NULL) {
449         return HDF_ERR_INVALID_OBJECT;
450     }
451     config = (struct I3cConfig *)OsalMemCalloc(sizeof(*config));
452     if (config == NULL) {
453         HDF_LOGE("func:%s config is NULL!", __func__);
454         return HDF_ERR_MALLOC_FAIL;
455     }
456     config->busMode = I3C_BUS_HDR_MODE;
457     config->curMaster = NULL;
458     // invalid handle
459     (void)I3cTransfer(NULL, g_msgs, 1, I3C_MODE);
460     (void)I3cSetConfig(NULL, config);
461     (void)I3cGetConfig(NULL, config);
462     (void)I3cRequestIbi(NULL, tester->config.devAddr, TestI3cIbiFunc, I3C_TEST_IBI_PAYLOAD);
463     (void)I3cFreeIbi(NULL, tester->config.devAddr);
464     // Invalid msg
465     (void)I3cTransfer(tester->handle, NULL, 1, I3C_MODE);
466     // Invalid config
467     (void)I3cSetConfig(tester->handle, NULL);
468     (void)I3cGetConfig(tester->handle, NULL);
469     // Invalid function
470     (void)I3cRequestIbi(tester->handle, tester->config.devAddr, NULL, I3C_TEST_IBI_PAYLOAD);
471     // Invalid number
472     (void)I3cTransfer(tester->handle, g_msgs, -1, I3C_MODE);
473     (void)I3cRequestIbi(tester->handle, tester->config.devAddr, TestI3cIbiFunc, -1);
474     *((int32_t *)param) = 1;
475     HDF_LOGD("%s: Done", __func__);
476 
477     return HDF_SUCCESS;
478 }
479 
480 static struct I3cTestEntry g_entry[] = {
481     { I3C_TEST_CMD_TRANSFER, I3cTestTransfer, "I3cTestTransfer" },
482     { I3C_TEST_CMD_SET_CONFIG, I3cTestSetConfig, "I3cTestSetConfig" },
483     { I3C_TEST_CMD_GET_CONFIG, I3cTestGetConfig, "I3cTestGetConfig" },
484     { I3C_TEST_CMD_REQUEST_IBI, I3cTestRequestIbi, "I3cTestRequestIbi" },
485     { I3C_TEST_CMD_FREE_IBI, I3cTestFreeIbi, "I3cTestFreeIbi" },
486     { I3C_TEST_CMD_MULTI_THREAD, I3cTestMultiThread, "I3cTestMultiThread" },
487     { I3C_TEST_CMD_RELIABILITY, I3cTestReliability, "I3cTestReliability" },
488     { I3C_TEST_CMD_SETUP_ALL, I3cTestSetUpAll, "I3cTestSetUpAll" },
489     { I3C_TEST_CMD_TEARDOWN_ALL, I3cTestTearDownAll, "I3cTestTearDownAll" },
490 };
491 
I3cTestExecute(int cmd)492 int32_t I3cTestExecute(int cmd)
493 {
494     uint32_t i;
495     int32_t count;
496     int32_t ret = HDF_ERR_NOT_SUPPORT;
497 
498     if (cmd > I3C_TEST_CMD_MAX) {
499         HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
500         ret = HDF_ERR_NOT_SUPPORT;
501         HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
502         return ret;
503     }
504 
505     for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
506         if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
507             continue;
508         }
509         count = 0;
510         ret = g_entry[i].func((void *)&count);
511         break;
512     }
513 
514     HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
515     return ret;
516 }
517