1 /*
2  * Copyright (c) 2021 Vestas Wind Systems A/S
3  * Copyright (c) 2018 Alexander Wachter
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT zephyr_can_loopback
9 
10 #include <stdbool.h>
11 #include <string.h>
12 
13 #include <zephyr/drivers/can.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/logging/log.h>
16 
17 LOG_MODULE_REGISTER(can_loopback, CONFIG_CAN_LOG_LEVEL);
18 
19 struct can_loopback_frame {
20 	struct can_frame frame;
21 	can_tx_callback_t cb;
22 	void *cb_arg;
23 };
24 
25 struct can_loopback_filter {
26 	can_rx_callback_t rx_cb;
27 	void *cb_arg;
28 	struct can_filter filter;
29 };
30 
31 struct can_loopback_data {
32 	struct can_loopback_filter filters[CONFIG_CAN_MAX_FILTER];
33 	struct k_mutex mtx;
34 	struct k_msgq tx_msgq;
35 	char msgq_buffer[CONFIG_CAN_LOOPBACK_TX_MSGQ_SIZE * sizeof(struct can_loopback_frame)];
36 	struct k_thread tx_thread_data;
37 	bool started;
38 	bool loopback;
39 #ifdef CONFIG_CAN_FD_MODE
40 	bool fd;
41 #endif /* CONFIG_CAN_FD_MODE */
42 
43 	K_KERNEL_STACK_MEMBER(tx_thread_stack,
44 		      CONFIG_CAN_LOOPBACK_TX_THREAD_STACK_SIZE);
45 };
46 
receive_frame(const struct device * dev,const struct can_frame * frame,struct can_loopback_filter * filter)47 static void receive_frame(const struct device *dev,
48 			  const struct can_frame *frame,
49 			  struct can_loopback_filter *filter)
50 {
51 	struct can_frame frame_tmp = *frame;
52 
53 	LOG_DBG("Receiving %d bytes. Id: 0x%x, ID type: %s %s",
54 		frame->dlc, frame->id,
55 		(frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
56 		(frame->flags & CAN_FRAME_RTR) != 0 ? ", RTR frame" : "");
57 
58 	filter->rx_cb(dev, &frame_tmp, filter->cb_arg);
59 }
60 
tx_thread(void * arg1,void * arg2,void * arg3)61 static void tx_thread(void *arg1, void *arg2, void *arg3)
62 {
63 	const struct device *dev = arg1;
64 	struct can_loopback_data *data = dev->data;
65 	struct can_loopback_frame frame;
66 	struct can_loopback_filter *filter;
67 	int ret;
68 
69 	ARG_UNUSED(arg2);
70 	ARG_UNUSED(arg3);
71 
72 	while (1) {
73 		ret = k_msgq_get(&data->tx_msgq, &frame, K_FOREVER);
74 		if (ret < 0) {
75 			LOG_DBG("Pend on TX queue returned without valid frame (err %d)", ret);
76 			continue;
77 		}
78 		frame.cb(dev, 0, frame.cb_arg);
79 
80 		if (!data->loopback) {
81 			continue;
82 		}
83 
84 		k_mutex_lock(&data->mtx, K_FOREVER);
85 
86 		for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
87 			filter = &data->filters[i];
88 			if (filter->rx_cb != NULL &&
89 			    can_frame_matches_filter(&frame.frame, &filter->filter)) {
90 				receive_frame(dev, &frame.frame, filter);
91 			}
92 		}
93 
94 		k_mutex_unlock(&data->mtx);
95 	}
96 }
97 
can_loopback_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)98 static int can_loopback_send(const struct device *dev,
99 			     const struct can_frame *frame,
100 			     k_timeout_t timeout, can_tx_callback_t callback,
101 			     void *user_data)
102 {
103 	struct can_loopback_data *data = dev->data;
104 	struct can_loopback_frame loopback_frame;
105 	uint8_t max_dlc = CAN_MAX_DLC;
106 	int ret;
107 
108 	__ASSERT_NO_MSG(callback != NULL);
109 
110 	LOG_DBG("Sending %d bytes on %s. Id: 0x%x, ID type: %s %s",
111 		frame->dlc, dev->name, frame->id,
112 		(frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
113 		(frame->flags & CAN_FRAME_RTR) != 0 ? ", RTR frame" : "");
114 
115 #ifdef CONFIG_CAN_FD_MODE
116 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR |
117 		CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0) {
118 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
119 		return -ENOTSUP;
120 	}
121 
122 	if ((frame->flags & CAN_FRAME_FDF) != 0) {
123 		if (!data->fd) {
124 			return -ENOTSUP;
125 		}
126 
127 		max_dlc = CANFD_MAX_DLC;
128 	}
129 #else /* CONFIG_CAN_FD_MODE */
130 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR)) != 0) {
131 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
132 		return -ENOTSUP;
133 	}
134 #endif /* !CONFIG_CAN_FD_MODE */
135 
136 	if (frame->dlc > max_dlc) {
137 		LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, max_dlc);
138 		return -EINVAL;
139 	}
140 
141 	if (!data->started) {
142 		return -ENETDOWN;
143 	}
144 
145 	loopback_frame.frame = *frame;
146 	loopback_frame.cb = callback;
147 	loopback_frame.cb_arg = user_data;
148 
149 	ret = k_msgq_put(&data->tx_msgq, &loopback_frame, timeout);
150 	if (ret < 0) {
151 		LOG_DBG("TX queue full (err %d)", ret);
152 		return -EAGAIN;
153 	}
154 
155 	return 0;
156 }
157 
158 
get_free_filter(struct can_loopback_filter * filters)159 static inline int get_free_filter(struct can_loopback_filter *filters)
160 {
161 	for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
162 		if (filters[i].rx_cb == NULL) {
163 			return i;
164 		}
165 	}
166 
167 	return -ENOSPC;
168 }
169 
can_loopback_add_rx_filter(const struct device * dev,can_rx_callback_t cb,void * cb_arg,const struct can_filter * filter)170 static int can_loopback_add_rx_filter(const struct device *dev, can_rx_callback_t cb,
171 				      void *cb_arg, const struct can_filter *filter)
172 {
173 	struct can_loopback_data *data = dev->data;
174 	struct can_loopback_filter *loopback_filter;
175 	int filter_id;
176 
177 	LOG_DBG("Setting filter ID: 0x%x, mask: 0x%x", filter->id, filter->mask);
178 
179 #ifdef CONFIG_CAN_FD_MODE
180 	if ((filter->flags & ~(CAN_FILTER_IDE | CAN_FILTER_DATA |
181 							CAN_FILTER_RTR | CAN_FILTER_FDF)) != 0) {
182 #else
183 	if ((filter->flags & ~(CAN_FILTER_IDE | CAN_FILTER_DATA | CAN_FILTER_RTR)) != 0) {
184 #endif
185 		LOG_ERR("unsupported CAN filter flags 0x%02x", filter->flags);
186 		return -ENOTSUP;
187 	}
188 
189 	k_mutex_lock(&data->mtx, K_FOREVER);
190 	filter_id = get_free_filter(data->filters);
191 
192 	if (filter_id < 0) {
193 		LOG_ERR("No free filter left");
194 		k_mutex_unlock(&data->mtx);
195 		return filter_id;
196 	}
197 
198 	loopback_filter = &data->filters[filter_id];
199 
200 	loopback_filter->rx_cb = cb;
201 	loopback_filter->cb_arg = cb_arg;
202 	loopback_filter->filter = *filter;
203 	k_mutex_unlock(&data->mtx);
204 
205 	LOG_DBG("Filter added. ID: %d", filter_id);
206 
207 	return filter_id;
208 }
209 
210 static void can_loopback_remove_rx_filter(const struct device *dev, int filter_id)
211 {
212 	struct can_loopback_data *data = dev->data;
213 
214 	if (filter_id >= ARRAY_SIZE(data->filters)) {
215 		LOG_ERR("filter ID %d out-of-bounds", filter_id);
216 		return;
217 	}
218 
219 	LOG_DBG("Remove filter ID: %d", filter_id);
220 	k_mutex_lock(&data->mtx, K_FOREVER);
221 	data->filters[filter_id].rx_cb = NULL;
222 	k_mutex_unlock(&data->mtx);
223 }
224 
225 static int can_loopback_get_capabilities(const struct device *dev, can_mode_t *cap)
226 {
227 	ARG_UNUSED(dev);
228 
229 	*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK;
230 
231 #if CONFIG_CAN_FD_MODE
232 	*cap |= CAN_MODE_FD;
233 #endif /* CONFIG_CAN_FD_MODE */
234 
235 	return 0;
236 }
237 
238 static int can_loopback_start(const struct device *dev)
239 {
240 	struct can_loopback_data *data = dev->data;
241 
242 	if (data->started) {
243 		return -EALREADY;
244 	}
245 
246 	data->started = true;
247 
248 	return 0;
249 }
250 
251 static int can_loopback_stop(const struct device *dev)
252 {
253 	struct can_loopback_data *data = dev->data;
254 
255 	if (!data->started) {
256 		return -EALREADY;
257 	}
258 
259 	data->started = false;
260 
261 	k_msgq_purge(&data->tx_msgq);
262 
263 	return 0;
264 }
265 
266 static int can_loopback_set_mode(const struct device *dev, can_mode_t mode)
267 {
268 	struct can_loopback_data *data = dev->data;
269 
270 	if (data->started) {
271 		return -EBUSY;
272 	}
273 
274 #ifdef CONFIG_CAN_FD_MODE
275 	if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_FD)) != 0) {
276 		LOG_ERR("unsupported mode: 0x%08x", mode);
277 		return -ENOTSUP;
278 	}
279 
280 	data->fd = (mode & CAN_MODE_FD) != 0;
281 #else
282 	if ((mode & ~(CAN_MODE_LOOPBACK)) != 0) {
283 		LOG_ERR("unsupported mode: 0x%08x", mode);
284 		return -ENOTSUP;
285 	}
286 #endif /* CONFIG_CAN_FD_MODE */
287 
288 	data->loopback = (mode & CAN_MODE_LOOPBACK) != 0;
289 
290 	return 0;
291 }
292 
293 static int can_loopback_set_timing(const struct device *dev,
294 				   const struct can_timing *timing)
295 {
296 	struct can_loopback_data *data = dev->data;
297 
298 	ARG_UNUSED(timing);
299 
300 	if (data->started) {
301 		return -EBUSY;
302 	}
303 
304 	return 0;
305 }
306 
307 #ifdef CONFIG_CAN_FD_MODE
308 static int can_loopback_set_timing_data(const struct device *dev,
309 					const struct can_timing *timing)
310 {
311 	struct can_loopback_data *data = dev->data;
312 
313 	ARG_UNUSED(timing);
314 
315 	if (data->started) {
316 		return -EBUSY;
317 	}
318 
319 	return 0;
320 }
321 #endif /* CONFIG_CAN_FD_MODE */
322 
323 static int can_loopback_get_state(const struct device *dev, enum can_state *state,
324 				  struct can_bus_err_cnt *err_cnt)
325 {
326 	struct can_loopback_data *data = dev->data;
327 
328 	if (state != NULL) {
329 		if (data->started) {
330 			*state = CAN_STATE_ERROR_ACTIVE;
331 		} else {
332 			*state = CAN_STATE_STOPPED;
333 		}
334 	}
335 
336 	if (err_cnt) {
337 		err_cnt->tx_err_cnt = 0;
338 		err_cnt->rx_err_cnt = 0;
339 	}
340 
341 	return 0;
342 }
343 
344 #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
345 static int can_loopback_recover(const struct device *dev, k_timeout_t timeout)
346 {
347 	struct can_loopback_data *data = dev->data;
348 
349 	ARG_UNUSED(timeout);
350 
351 	if (!data->started) {
352 		return -ENETDOWN;
353 	}
354 
355 	return 0;
356 }
357 #endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
358 
359 static void can_loopback_set_state_change_callback(const struct device *dev,
360 						   can_state_change_callback_t cb,
361 						   void *user_data)
362 {
363 	ARG_UNUSED(dev);
364 	ARG_UNUSED(cb);
365 	ARG_UNUSED(user_data);
366 }
367 
368 static int can_loopback_get_core_clock(const struct device *dev, uint32_t *rate)
369 {
370 	/* Return 16MHz as an realistic value for the testcases */
371 	*rate = 16000000;
372 	return 0;
373 }
374 
375 static int can_loopback_get_max_filters(const struct device *dev, bool ide)
376 {
377 	ARG_UNUSED(ide);
378 
379 	return CONFIG_CAN_MAX_FILTER;
380 }
381 
382 static const struct can_driver_api can_loopback_driver_api = {
383 	.get_capabilities = can_loopback_get_capabilities,
384 	.start = can_loopback_start,
385 	.stop = can_loopback_stop,
386 	.set_mode = can_loopback_set_mode,
387 	.set_timing = can_loopback_set_timing,
388 	.send = can_loopback_send,
389 	.add_rx_filter = can_loopback_add_rx_filter,
390 	.remove_rx_filter = can_loopback_remove_rx_filter,
391 	.get_state = can_loopback_get_state,
392 #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
393 	.recover = can_loopback_recover,
394 #endif
395 	.set_state_change_callback = can_loopback_set_state_change_callback,
396 	.get_core_clock = can_loopback_get_core_clock,
397 	.get_max_filters = can_loopback_get_max_filters,
398 	.timing_min = {
399 		.sjw = 0x1,
400 		.prop_seg = 0x01,
401 		.phase_seg1 = 0x01,
402 		.phase_seg2 = 0x01,
403 		.prescaler = 0x01
404 	},
405 	.timing_max = {
406 		.sjw = 0x0F,
407 		.prop_seg = 0x0F,
408 		.phase_seg1 = 0x0F,
409 		.phase_seg2 = 0x0F,
410 		.prescaler = 0xFFFF
411 	},
412 #ifdef CONFIG_CAN_FD_MODE
413 	.set_timing_data = can_loopback_set_timing_data,
414 	.timing_data_min = {
415 		.sjw = 0x1,
416 		.prop_seg = 0x01,
417 		.phase_seg1 = 0x01,
418 		.phase_seg2 = 0x01,
419 		.prescaler = 0x01
420 	},
421 	.timing_data_max = {
422 		.sjw = 0x0F,
423 		.prop_seg = 0x0F,
424 		.phase_seg1 = 0x0F,
425 		.phase_seg2 = 0x0F,
426 		.prescaler = 0xFFFF
427 	},
428 #endif /* CONFIG_CAN_FD_MODE */
429 };
430 
431 static int can_loopback_init(const struct device *dev)
432 {
433 	struct can_loopback_data *data = dev->data;
434 	k_tid_t tx_tid;
435 
436 	k_mutex_init(&data->mtx);
437 
438 	for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
439 		data->filters[i].rx_cb = NULL;
440 	}
441 
442 	k_msgq_init(&data->tx_msgq, data->msgq_buffer, sizeof(struct can_loopback_frame),
443 		    CONFIG_CAN_LOOPBACK_TX_MSGQ_SIZE);
444 
445 	tx_tid = k_thread_create(&data->tx_thread_data, data->tx_thread_stack,
446 				 K_KERNEL_STACK_SIZEOF(data->tx_thread_stack),
447 				 tx_thread, (void *)dev, NULL, NULL,
448 				 CONFIG_CAN_LOOPBACK_TX_THREAD_PRIORITY,
449 				 0, K_NO_WAIT);
450 	if (!tx_tid) {
451 		LOG_ERR("ERROR spawning tx thread");
452 		return -1;
453 	}
454 
455 	LOG_INF("Init of %s done", dev->name);
456 
457 	return 0;
458 }
459 
460 #define CAN_LOOPBACK_INIT(inst)						\
461 	static struct can_loopback_data can_loopback_dev_data_##inst;	\
462 									\
463 	CAN_DEVICE_DT_INST_DEFINE(inst, can_loopback_init, NULL,	\
464 				  &can_loopback_dev_data_##inst, NULL,	\
465 				  POST_KERNEL, CONFIG_CAN_INIT_PRIORITY,\
466 				  &can_loopback_driver_api);
467 
468 DT_INST_FOREACH_STATUS_OKAY(CAN_LOOPBACK_INIT)
469