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