1 /*
2 * Copyright (c) 2022 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 "can_test.h"
10 #include "can_if.h"
11 #include "device_resource_if.h"
12 #include "hdf_device_desc.h"
13 #include "hdf_io_service_if.h"
14 #include "hdf_log.h"
15 #include "osal_mem.h"
16 #include "osal_thread.h"
17 #include "osal_time.h"
18 #include "platform_assert.h"
19 #include "securec.h"
20
21 #define HDF_LOG_TAG can_test
22 #define CAN_TEST_STACK_SIZE (1024 * 10)
23
24 #define CAN_TEST_ID_A 0x15A
25 #define CAN_TEST_ID_B 0x2A5
26 #define CAN_TEST_ID_C 0x555
27 #define CAN_MASK_FULL 0x1FFFFFFF
28 #define CAN_TEST_DATA 0xAB
29
30 #define CAN_TEST_TIMEOUT_20 20
31 #define CAN_TEST_TIMEOUT_10 10
32
33 static struct HdfDeviceObject hdfDev = {
34 .service = NULL,
35 .property = NULL,
36 .priv = NULL,
37 };
38
39 struct HdfDriverEntry *CanVirtualGetEntry(void);
40 static struct HdfDriverEntry *g_driverEntry = NULL;
41 static uint16_t g_busNum;
42 static DevHandle g_handle;
43 static struct CanMsg g_msgA;
44 static struct CanMsg g_msgB;
45 static struct CanMsg g_msgC;
46
47 static struct CanFilter g_filterA = {
48 .rtr = 0,
49 .ide = 0,
50 .id = CAN_TEST_ID_A,
51 .rtrMask = 1,
52 .ideMask = 1,
53 .idMask = CAN_MASK_FULL,
54 };
55
56 static struct CanFilter g_filterB = {
57 .rtr = 0,
58 .ide = 0,
59 .id = CAN_TEST_ID_B,
60 .rtrMask = 1,
61 .ideMask = 1,
62 .idMask = CAN_MASK_FULL,
63 };
64
CanMsgInitByParms(struct CanMsg * msg,uint32_t id,uint32_t ide,uint32_t rtr,uint8_t data)65 static void CanMsgInitByParms(struct CanMsg *msg, uint32_t id, uint32_t ide, uint32_t rtr, uint8_t data)
66 {
67 msg->ide = ide;
68 msg->id = id;
69 msg->rtr = rtr;
70 if (memset_s(msg->data, sizeof(msg->data), data, sizeof(msg->data)) != EOK) {
71 HDF_LOGW("CanMsgInitByParms: init data failed");
72 }
73 msg->dlc = sizeof(msg->data);
74 msg->error = 0;
75 }
76
CanTestGetConfig(struct CanTestConfig * config)77 static int32_t CanTestGetConfig(struct CanTestConfig *config)
78 {
79 int32_t ret;
80 struct HdfSBuf *reply = NULL;
81 struct HdfIoService *service = NULL;
82 const void *buf = NULL;
83 uint32_t len;
84
85 HDF_LOGD("CanTestGetConfig: enter!");
86 service = HdfIoServiceBind("CAN_TEST");
87 if (service == NULL) {
88 return HDF_ERR_NOT_SUPPORT;
89 }
90 do {
91 reply = HdfSbufObtain(sizeof(*config) + sizeof(uint64_t));
92 if (reply == NULL) {
93 HDF_LOGE("CanTestGetConfig: failed to obtain reply!");
94 ret = HDF_ERR_MALLOC_FAIL;
95 break;
96 }
97
98 ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
99 if (ret != HDF_SUCCESS) {
100 HDF_LOGE("CanTestGetConfig: remote dispatch fail:%d", ret);
101 break;
102 }
103
104 if (!HdfSbufReadBuffer(reply, &buf, &len)) {
105 HDF_LOGE("CanTestGetConfig: read buf fail!");
106 ret = HDF_ERR_IO;
107 break;
108 }
109
110 if (len != sizeof(*config)) {
111 HDF_LOGE("CanTestGetConfig: config size:%u, but read size:%u!", sizeof(*config), len);
112 ret = HDF_ERR_IO;
113 break;
114 }
115
116 if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
117 HDF_LOGE("CanTestGetConfig: memcpy buf fail!");
118 ret = HDF_ERR_IO;
119 break;
120 }
121
122 HDF_LOGV("CanTestGetConfig: test on bus:0x%x, bitRate:%u, workMode:0x%x", config->busNum, config->bitRate,
123 config->workMode);
124 HDF_LOGD("CanTestGetConfig: exit!");
125 ret = HDF_SUCCESS;
126 } while (0);
127 HdfSbufRecycle(reply);
128 HdfIoServiceRecycle(service);
129 return ret;
130 }
131
CanTestSetUpByConfig(struct CanTestConfig * config)132 static int32_t CanTestSetUpByConfig(struct CanTestConfig *config)
133 {
134 struct CanConfig cfg;
135 g_busNum = config->busNum;
136 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusOpen(g_busNum, &g_handle));
137 CHECK_FALSE_RETURN(g_handle == NULL);
138 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusGetCfg(g_handle, &cfg));
139 cfg.speed = config->bitRate;
140 cfg.mode = config->workMode;
141 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSetCfg(g_handle, &cfg));
142 CanMsgInitByParms(&g_msgA, CAN_TEST_ID_A, 0, 0, CAN_TEST_DATA);
143 CanMsgInitByParms(&g_msgB, CAN_TEST_ID_B, 0, 0, CAN_TEST_DATA);
144 CanMsgInitByParms(&g_msgC, CAN_TEST_ID_C, 0, 0, CAN_TEST_DATA);
145 return HDF_SUCCESS;
146 }
147
CanTestSetUpEveryCase(void)148 static int32_t CanTestSetUpEveryCase(void)
149 {
150 struct CanTestConfig config;
151
152 if (CanTestGetConfig(&config) != HDF_SUCCESS) {
153 HDF_LOGW("CanTestSetUpEveryCase: get config failed, using default config...");
154 config.bitRate = CAN_TEST_BIT_RATE;
155 config.workMode = CAN_TEST_WORK_MODE;
156 config.busNum = CAN_TEST_BUS_NUM;
157 g_driverEntry = CanVirtualGetEntry();
158 CHECK_FALSE_RETURN(g_driverEntry == NULL);
159 LONGS_EQUAL_RETURN(HDF_SUCCESS, g_driverEntry->Init(&hdfDev));
160 }
161 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanTestSetUpByConfig(&config));
162 return HDF_SUCCESS;
163 }
164
CanTestTearDownEveryCase(void)165 static int32_t CanTestTearDownEveryCase(void)
166 {
167 CanBusClose(g_handle);
168 if (g_driverEntry != NULL) {
169 g_driverEntry->Release(&hdfDev);
170 g_driverEntry = NULL;
171 }
172 return HDF_SUCCESS;
173 }
174
CanMsgEquals(const struct CanMsg * msgA,const struct CanMsg * msgB)175 static bool CanMsgEquals(const struct CanMsg *msgA, const struct CanMsg *msgB)
176 {
177 int i;
178 if (msgA->ide != msgB->ide) {
179 return false;
180 }
181 if (msgA->id != msgB->id) {
182 return false;
183 }
184 if (msgA->rtr != msgB->rtr) {
185 return false;
186 }
187 if (msgA->dlc != msgB->dlc) {
188 return false;
189 }
190 for (i = 0; i < msgA->dlc; i++) {
191 if (msgA->data[i] != msgB->data[i]) {
192 return false;
193 }
194 }
195 return true;
196 }
197
CanBusCanNotReadMsg(DevHandle handle,struct CanMsg * msg)198 static bool CanBusCanNotReadMsg(DevHandle handle, struct CanMsg *msg)
199 {
200 struct CanMsg msgGot;
201 (void)msg;
202 LONGS_EQUAL_RETURN(HDF_ERR_TIMEOUT, CanBusReadMsg(handle, &msgGot, CAN_TEST_TIMEOUT_10));
203 return true;
204 }
205
CanBusCanReadMsg(DevHandle handle,struct CanMsg * msg)206 static bool CanBusCanReadMsg(DevHandle handle, struct CanMsg *msg)
207 {
208 struct CanMsg msgGot;
209 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusReadMsg(handle, &msgGot, CAN_TEST_TIMEOUT_10));
210 CHECK_TRUE_RETURN(CanMsgEquals(msg, &msgGot));
211 return true;
212 }
213
CanBusCanSendAndReadMsg(DevHandle handle,struct CanMsg * msg)214 static bool CanBusCanSendAndReadMsg(DevHandle handle, struct CanMsg *msg)
215 {
216 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(handle, msg));
217 return CanBusCanReadMsg(handle, msg);
218 }
219
CanTestSendAndRead(void)220 static int32_t CanTestSendAndRead(void)
221 {
222 CHECK_TRUE_RETURN(CanBusCanSendAndReadMsg(g_handle, &g_msgA));
223 return HDF_SUCCESS;
224 }
225
CanTestNoBlockRead(void)226 static int32_t CanTestNoBlockRead(void)
227 {
228 struct CanMsg msg;
229 CHECK_FALSE_RETURN(HDF_ERR_TIMEOUT == CanBusReadMsg(g_handle, &msg, 0));
230 return HDF_SUCCESS;
231 }
232
CanTestBlockRead(void)233 static int32_t CanTestBlockRead(void)
234 {
235 struct CanMsg msg;
236 LONGS_EQUAL_RETURN(HDF_ERR_TIMEOUT, CanBusReadMsg(g_handle, &msg, CAN_TEST_TIMEOUT_10));
237 return HDF_SUCCESS;
238 }
239
CanTestAddAndDelFilter(void)240 static int32_t CanTestAddAndDelFilter(void)
241 {
242 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusAddFilter(g_handle, &g_filterA));
243 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgA));
244 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgB));
245 CHECK_TRUE_RETURN(CanBusCanReadMsg(g_handle, &g_msgA));
246 CHECK_TRUE_RETURN(CanBusCanNotReadMsg(g_handle, &g_msgB)); // filter out ...
247
248 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusDelFilter(g_handle, &g_filterA));
249 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgB));
250 CHECK_TRUE_RETURN(CanBusCanReadMsg(g_handle, &g_msgB)); // filter out ...
251 return HDF_SUCCESS;
252 }
253
CanTestAddMultiFilter(void)254 static int32_t CanTestAddMultiFilter(void)
255 {
256 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusAddFilter(g_handle, &g_filterA));
257 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusAddFilter(g_handle, &g_filterB));
258
259 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgA));
260 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgB));
261 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgC));
262
263 CHECK_TRUE_RETURN(CanBusCanReadMsg(g_handle, &g_msgA));
264 CHECK_TRUE_RETURN(CanBusCanReadMsg(g_handle, &g_msgB));
265 CHECK_TRUE_RETURN(CanBusCanNotReadMsg(g_handle, &g_msgC));
266
267 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusDelFilter(g_handle, &g_filterA));
268 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusDelFilter(g_handle, &g_filterB));
269
270 CHECK_TRUE_RETURN(CanBusCanSendAndReadMsg(g_handle, &g_msgC));
271 return HDF_SUCCESS;
272 }
273
CanTestGetBusState(void)274 static int32_t CanTestGetBusState(void)
275 {
276 int32_t ret;
277 ret = CanBusGetState(g_handle);
278 if (ret == HDF_ERR_NOT_SUPPORT) {
279 return HDF_SUCCESS;
280 }
281 CHECK_TRUE_RETURN(ret >= CAN_BUS_RESET && ret < CAN_BUS_INVALID);
282 return HDF_SUCCESS;
283 }
284
CanTestStartTestThread(OsalThreadEntry entry,DevHandle handle)285 static struct OsalThread *CanTestStartTestThread(OsalThreadEntry entry, DevHandle handle)
286 {
287 int32_t ret;
288 struct OsalThreadParam threadCfg;
289 struct OsalThread *thread = (struct OsalThread *)OsalMemCalloc(sizeof(*thread));
290
291 ret = OsalThreadCreate(thread, (OsalThreadEntry)entry, (void *)handle);
292 if (ret != HDF_SUCCESS) {
293 HDF_LOGE("create test thread fail:%d", ret);
294 return NULL;
295 }
296
297 threadCfg.name = (char *)"CanTestPoller";
298 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
299 threadCfg.stackSize = CAN_TEST_STACK_SIZE;
300
301 ret = OsalThreadStart(thread, &threadCfg);
302 if (ret != HDF_SUCCESS) {
303 (void)OsalThreadDestroy(thread);
304 HDF_LOGE("start test thread2 fail:%d", ret);
305 return NULL;
306 }
307
308 return thread;
309 }
310
CanTestStopTestThread(struct OsalThread * thread)311 static void CanTestStopTestThread(struct OsalThread *thread)
312 {
313 if (thread == NULL) {
314 return;
315 }
316 (void)OsalThreadDestroy(thread);
317 OsalMemFree(thread);
318 }
319
CanTestReaderFunc(void * param)320 static int CanTestReaderFunc(void *param)
321 {
322 struct CanMsg msg;
323 DevHandle handle = (DevHandle)param;
324
325 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusReadMsg(handle, &msg, CAN_TEST_TIMEOUT_10));
326 return HDF_SUCCESS;
327 }
328
CanTestSenderFunc(void * param)329 static int CanTestSenderFunc(void *param)
330 {
331 DevHandle handle = (DevHandle)param;
332
333 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(handle, &g_msgA));
334 return HDF_SUCCESS;
335 }
336
CanTestMultiThreadReadSameHandle(void)337 static int32_t CanTestMultiThreadReadSameHandle(void)
338 {
339 struct CanMsg msgGot;
340 struct OsalThread *thread = NULL;
341 thread = CanTestStartTestThread(CanTestReaderFunc, g_handle);
342 CHECK_FALSE_RETURN(thread == NULL);
343 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgA));
344 OsalMSleep(CAN_TEST_TIMEOUT_20);
345 CHECK_FALSE_RETURN(CanBusReadMsg(g_handle, &msgGot, 0) == HDF_SUCCESS);
346 CanTestStopTestThread(thread);
347 return HDF_SUCCESS;
348 }
349
CanTestMultiThreadReadMultiHandle(void)350 static int32_t CanTestMultiThreadReadMultiHandle(void)
351 {
352 struct CanMsg msgGot;
353 struct OsalThread *thread = NULL;
354 DevHandle handle = NULL;
355
356 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusOpen(g_busNum, &handle));
357 thread = CanTestStartTestThread(CanTestReaderFunc, handle);
358 CHECK_FALSE_RETURN(thread == NULL);
359 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusSendMsg(g_handle, &g_msgA));
360 OsalMSleep(CAN_TEST_TIMEOUT_20);
361 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusReadMsg(g_handle, &msgGot, 0));
362 CanTestStopTestThread(thread);
363 CanBusClose(handle);
364 return HDF_SUCCESS;
365 }
366
CanTestMultiThreadSendSameHandle(void)367 static int32_t CanTestMultiThreadSendSameHandle(void)
368 {
369 struct CanMsg msgGot;
370 struct OsalThread *thread = NULL;
371
372 thread = CanTestStartTestThread(CanTestSenderFunc, g_handle);
373 CHECK_FALSE_RETURN(thread == NULL);
374 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusReadMsg(g_handle, &msgGot, CAN_TEST_TIMEOUT_10));
375 CanTestStopTestThread(thread);
376 return HDF_SUCCESS;
377 }
378
CanTestMultiThreadSendMultiHandle(void)379 static int32_t CanTestMultiThreadSendMultiHandle(void)
380 {
381 struct CanMsg msgGot;
382 struct OsalThread *thread = NULL;
383 DevHandle handle = NULL;
384
385 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusOpen(g_busNum, &handle));
386 thread = CanTestStartTestThread(CanTestSenderFunc, g_handle);
387 CHECK_FALSE_RETURN(thread == NULL);
388 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusReadMsg(handle, &msgGot, CAN_TEST_TIMEOUT_10));
389 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanBusReadMsg(g_handle, &msgGot, CAN_TEST_TIMEOUT_10));
390 CanTestStopTestThread(thread);
391 CanBusClose(handle);
392 return HDF_SUCCESS;
393 }
394
CanTestReliability(void)395 static int32_t CanTestReliability(void)
396 {
397 int32_t ret;
398 struct CanMsg msg;
399 struct CanFilter filter;
400 struct CanConfig cfg;
401 DevHandle handle = g_handle;
402
403 /* invalid device handle */
404 ret = CanBusSendMsg(NULL, &msg);
405 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
406 ret = CanBusReadMsg(NULL, &msg, 0);
407 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
408 ret = CanBusReadMsg(NULL, &msg, 1);
409 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
410 ret = CanBusSetCfg(NULL, &cfg);
411 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
412 ret = CanBusGetCfg(NULL, &cfg);
413 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
414 ret = CanBusAddFilter(NULL, &filter);
415 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
416 ret = CanBusDelFilter(NULL, &filter);
417 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
418 ret = CanBusGetState(NULL);
419 CHECK_LT_RETURN(ret, 0, HDF_FAILURE);
420
421 /* invalid parmas */
422 ret = CanBusSendMsg(handle, NULL);
423 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
424 ret = CanBusReadMsg(handle, NULL, 0);
425 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
426 ret = CanBusReadMsg(handle, NULL, 1);
427 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
428 ret = CanBusSetCfg(handle, NULL);
429 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
430 ret = CanBusGetCfg(handle, NULL);
431 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
432 ret = CanBusAddFilter(handle, &filter);
433 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
434 ret = CanBusDelFilter(handle, &filter);
435 CHECK_NE_RETURN(ret, HDF_SUCCESS, HDF_FAILURE);
436
437 return HDF_SUCCESS;
438 }
439
440 struct CanTestEntry {
441 int cmd;
442 int32_t (*func)(void);
443 const char *name;
444 };
445
446 static struct CanTestEntry g_testEntry[] = {
447 { CAN_TEST_SEND_AND_READ, CanTestSendAndRead, "should_send_and_read_msg_success" },
448 { CAN_TEST_NO_BLOCK_READ, CanTestNoBlockRead, "should_return_immediately_when_read_no_block" },
449 { CAN_TEST_BLOCK_READ, CanTestBlockRead, "should_return_timeout_when_read_block" },
450 { CAN_TEST_ADD_DEL_FILTER, CanTestAddAndDelFilter, "should_add_and_del_filter" },
451 { CAN_TEST_ADD_MULTI_FILTER, CanTestAddMultiFilter, "should_add_multi_filter" },
452 { CAN_TEST_GET_BUS_STATE, CanTestGetBusState, "should_get_bus_state_unless_not_supported" },
453 { CAN_TEST_MULTI_THREAD_READ_SAME_HANDLE, CanTestMultiThreadReadSameHandle,
454 "should_read_success_in_another_thread_by_the_same_handle" },
455 { CAN_TEST_MULTI_THREAD_READ_MULTI_HANDLE, CanTestMultiThreadReadMultiHandle,
456 "should_read_success_in_another_thread_by_another_handle" },
457 { CAN_TEST_MULTI_THREAD_SEND_SAME_HANDLE, CanTestMultiThreadSendSameHandle,
458 "should_send_success_in_another_thread_by_the_same_handle" },
459 { CAN_TEST_MULTI_THREAD_SEND_MULTI_HANDLE, CanTestMultiThreadSendMultiHandle,
460 "should_send_success_in_another_thread_by_another_handle" },
461 { CAN_TEST_RELIABILITY, CanTestReliability, "CanTestReliability" },
462 };
463
CanTestExecute(int cmd)464 int32_t CanTestExecute(int cmd)
465 {
466 int32_t ret;
467 uint32_t i;
468 struct CanTestEntry *entry = NULL;
469
470 if (cmd >= CAN_TEST_CMD_MAX) {
471 HDF_LOGE("CanTestExecute: invalid cmd:%d", cmd);
472 return HDF_ERR_NOT_SUPPORT;
473 }
474
475 for (i = 0; i < sizeof(g_testEntry) / sizeof(g_testEntry[0]); i++) {
476 if (g_testEntry[i].cmd != cmd || g_testEntry[i].func == NULL) {
477 continue;
478 }
479 entry = &g_testEntry[i];
480 break;
481 }
482
483 if (entry == NULL) {
484 HDF_LOGE("%s: no entry matched, cmd = %d", __func__, cmd);
485 return HDF_ERR_NOT_SUPPORT;
486 }
487
488 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanTestSetUpEveryCase());
489 ret = entry->func();
490 LONGS_EQUAL_RETURN(HDF_SUCCESS, CanTestTearDownEveryCase());
491
492 HDF_LOGE("[CanTestExecute][======cmd:%d====ret:%d======]", cmd, ret);
493 return ret;
494 }
495