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 #include <zephyr/sys/util.h>
17 
18 LOG_MODULE_REGISTER(can_loopback, CONFIG_CAN_LOG_LEVEL);
19 
20 struct can_loopback_frame {
21 	struct can_frame frame;
22 	can_tx_callback_t cb;
23 	void *cb_arg;
24 };
25 
26 struct can_loopback_filter {
27 	can_rx_callback_t rx_cb;
28 	void *cb_arg;
29 	struct can_filter filter;
30 };
31 
32 struct can_loopback_config {
33 	const struct can_driver_config common;
34 };
35 
36 struct can_loopback_data {
37 	struct can_driver_data common;
38 	struct can_loopback_filter filters[CONFIG_CAN_MAX_FILTER];
39 	struct k_mutex mtx;
40 	struct k_msgq tx_msgq;
41 	char msgq_buffer[CONFIG_CAN_LOOPBACK_TX_MSGQ_SIZE * sizeof(struct can_loopback_frame)];
42 	struct k_thread tx_thread_data;
43 
44 	K_KERNEL_STACK_MEMBER(tx_thread_stack,
45 		      CONFIG_CAN_LOOPBACK_TX_THREAD_STACK_SIZE);
46 };
47 
receive_frame(const struct device * dev,const struct can_frame * frame,struct can_loopback_filter * filter)48 static void receive_frame(const struct device *dev,
49 			  const struct can_frame *frame,
50 			  struct can_loopback_filter *filter)
51 {
52 	struct can_frame frame_tmp = *frame;
53 
54 	LOG_DBG("Receiving %d bytes. Id: 0x%x, ID type: %s %s",
55 		frame->dlc, frame->id,
56 		(frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
57 		(frame->flags & CAN_FRAME_RTR) != 0 ? ", RTR frame" : "");
58 
59 	filter->rx_cb(dev, &frame_tmp, filter->cb_arg);
60 }
61 
tx_thread(void * arg1,void * arg2,void * arg3)62 static void tx_thread(void *arg1, void *arg2, void *arg3)
63 {
64 	const struct device *dev = arg1;
65 	struct can_loopback_data *data = dev->data;
66 	struct can_loopback_frame frame;
67 	struct can_loopback_filter *filter;
68 	int ret;
69 
70 	ARG_UNUSED(arg2);
71 	ARG_UNUSED(arg3);
72 
73 	while (1) {
74 		ret = k_msgq_get(&data->tx_msgq, &frame, K_FOREVER);
75 		if (ret < 0) {
76 			LOG_DBG("Pend on TX queue returned without valid frame (err %d)", ret);
77 			continue;
78 		}
79 		frame.cb(dev, 0, frame.cb_arg);
80 
81 		if ((data->common.mode & CAN_MODE_LOOPBACK) == 0U) {
82 			continue;
83 		}
84 
85 #ifndef CONFIG_CAN_ACCEPT_RTR
86 		if ((frame.frame.flags & CAN_FRAME_RTR) != 0U) {
87 			continue;
88 		}
89 #endif /* !CONFIG_CAN_ACCEPT_RTR */
90 
91 		k_mutex_lock(&data->mtx, K_FOREVER);
92 
93 		for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
94 			filter = &data->filters[i];
95 			if (filter->rx_cb != NULL &&
96 			    can_frame_matches_filter(&frame.frame, &filter->filter)) {
97 				receive_frame(dev, &frame.frame, filter);
98 			}
99 		}
100 
101 		k_mutex_unlock(&data->mtx);
102 	}
103 }
104 
can_loopback_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)105 static int can_loopback_send(const struct device *dev,
106 			     const struct can_frame *frame,
107 			     k_timeout_t timeout, can_tx_callback_t callback,
108 			     void *user_data)
109 {
110 	struct can_loopback_data *data = dev->data;
111 	struct can_loopback_frame loopback_frame;
112 	uint8_t max_dlc = CAN_MAX_DLC;
113 	int ret;
114 
115 	LOG_DBG("Sending %d bytes on %s. Id: 0x%x, ID type: %s %s",
116 		frame->dlc, dev->name, frame->id,
117 		(frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
118 		(frame->flags & CAN_FRAME_RTR) != 0 ? ", RTR frame" : "");
119 
120 #ifdef CONFIG_CAN_FD_MODE
121 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR |
122 		CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0) {
123 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
124 		return -ENOTSUP;
125 	}
126 
127 	if ((frame->flags & CAN_FRAME_FDF) != 0) {
128 		if ((data->common.mode & CAN_MODE_FD) == 0U) {
129 			return -ENOTSUP;
130 		}
131 
132 		max_dlc = CANFD_MAX_DLC;
133 	}
134 #else /* CONFIG_CAN_FD_MODE */
135 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR)) != 0) {
136 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
137 		return -ENOTSUP;
138 	}
139 #endif /* !CONFIG_CAN_FD_MODE */
140 
141 	if (frame->dlc > max_dlc) {
142 		LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, max_dlc);
143 		return -EINVAL;
144 	}
145 
146 	if (!data->common.started) {
147 		return -ENETDOWN;
148 	}
149 
150 	loopback_frame.frame = *frame;
151 	loopback_frame.cb = callback;
152 	loopback_frame.cb_arg = user_data;
153 
154 	ret = k_msgq_put(&data->tx_msgq, &loopback_frame, timeout);
155 	if (ret < 0) {
156 		LOG_DBG("TX queue full (err %d)", ret);
157 		return -EAGAIN;
158 	}
159 
160 	return 0;
161 }
162 
163 
get_free_filter(struct can_loopback_filter * filters)164 static inline int get_free_filter(struct can_loopback_filter *filters)
165 {
166 	for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
167 		if (filters[i].rx_cb == NULL) {
168 			return i;
169 		}
170 	}
171 
172 	return -ENOSPC;
173 }
174 
can_loopback_add_rx_filter(const struct device * dev,can_rx_callback_t cb,void * cb_arg,const struct can_filter * filter)175 static int can_loopback_add_rx_filter(const struct device *dev, can_rx_callback_t cb,
176 				      void *cb_arg, const struct can_filter *filter)
177 {
178 	struct can_loopback_data *data = dev->data;
179 	struct can_loopback_filter *loopback_filter;
180 	int filter_id;
181 
182 	LOG_DBG("Setting filter ID: 0x%x, mask: 0x%x", filter->id, filter->mask);
183 
184 	if ((filter->flags & ~(CAN_FILTER_IDE)) != 0) {
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 
can_loopback_remove_rx_filter(const struct device * dev,int filter_id)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 < 0 || 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 
can_loopback_get_capabilities(const struct device * dev,can_mode_t * cap)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 
can_loopback_start(const struct device * dev)238 static int can_loopback_start(const struct device *dev)
239 {
240 	struct can_loopback_data *data = dev->data;
241 
242 	if (data->common.started) {
243 		return -EALREADY;
244 	}
245 
246 	data->common.started = true;
247 
248 	return 0;
249 }
250 
can_loopback_stop(const struct device * dev)251 static int can_loopback_stop(const struct device *dev)
252 {
253 	struct can_loopback_data *data = dev->data;
254 
255 	if (!data->common.started) {
256 		return -EALREADY;
257 	}
258 
259 	data->common.started = false;
260 
261 	k_msgq_purge(&data->tx_msgq);
262 
263 	return 0;
264 }
265 
can_loopback_set_mode(const struct device * dev,can_mode_t mode)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->common.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 #else
280 	if ((mode & ~(CAN_MODE_LOOPBACK)) != 0) {
281 		LOG_ERR("unsupported mode: 0x%08x", mode);
282 		return -ENOTSUP;
283 	}
284 #endif /* CONFIG_CAN_FD_MODE */
285 
286 	data->common.mode = mode;
287 
288 	return 0;
289 }
290 
can_loopback_set_timing(const struct device * dev,const struct can_timing * timing)291 static int can_loopback_set_timing(const struct device *dev,
292 				   const struct can_timing *timing)
293 {
294 	struct can_loopback_data *data = dev->data;
295 
296 	ARG_UNUSED(timing);
297 
298 	if (data->common.started) {
299 		return -EBUSY;
300 	}
301 
302 	return 0;
303 }
304 
305 #ifdef CONFIG_CAN_FD_MODE
can_loopback_set_timing_data(const struct device * dev,const struct can_timing * timing)306 static int can_loopback_set_timing_data(const struct device *dev,
307 					const struct can_timing *timing)
308 {
309 	struct can_loopback_data *data = dev->data;
310 
311 	ARG_UNUSED(timing);
312 
313 	if (data->common.started) {
314 		return -EBUSY;
315 	}
316 
317 	return 0;
318 }
319 #endif /* CONFIG_CAN_FD_MODE */
320 
can_loopback_get_state(const struct device * dev,enum can_state * state,struct can_bus_err_cnt * err_cnt)321 static int can_loopback_get_state(const struct device *dev, enum can_state *state,
322 				  struct can_bus_err_cnt *err_cnt)
323 {
324 	struct can_loopback_data *data = dev->data;
325 
326 	if (state != NULL) {
327 		if (data->common.started) {
328 			*state = CAN_STATE_ERROR_ACTIVE;
329 		} else {
330 			*state = CAN_STATE_STOPPED;
331 		}
332 	}
333 
334 	if (err_cnt) {
335 		err_cnt->tx_err_cnt = 0;
336 		err_cnt->rx_err_cnt = 0;
337 	}
338 
339 	return 0;
340 }
341 
can_loopback_set_state_change_callback(const struct device * dev,can_state_change_callback_t cb,void * user_data)342 static void can_loopback_set_state_change_callback(const struct device *dev,
343 						   can_state_change_callback_t cb,
344 						   void *user_data)
345 {
346 	ARG_UNUSED(dev);
347 	ARG_UNUSED(cb);
348 	ARG_UNUSED(user_data);
349 }
350 
can_loopback_get_core_clock(const struct device * dev,uint32_t * rate)351 static int can_loopback_get_core_clock(const struct device *dev, uint32_t *rate)
352 {
353 	ARG_UNUSED(dev);
354 
355 	/* Recommended CAN clock from CiA 601-3 */
356 	*rate = MHZ(80);
357 
358 	return 0;
359 }
360 
can_loopback_get_max_filters(const struct device * dev,bool ide)361 static int can_loopback_get_max_filters(const struct device *dev, bool ide)
362 {
363 	ARG_UNUSED(ide);
364 
365 	return CONFIG_CAN_MAX_FILTER;
366 }
367 
368 static DEVICE_API(can, can_loopback_driver_api) = {
369 	.get_capabilities = can_loopback_get_capabilities,
370 	.start = can_loopback_start,
371 	.stop = can_loopback_stop,
372 	.set_mode = can_loopback_set_mode,
373 	.set_timing = can_loopback_set_timing,
374 	.send = can_loopback_send,
375 	.add_rx_filter = can_loopback_add_rx_filter,
376 	.remove_rx_filter = can_loopback_remove_rx_filter,
377 	.get_state = can_loopback_get_state,
378 	.set_state_change_callback = can_loopback_set_state_change_callback,
379 	.get_core_clock = can_loopback_get_core_clock,
380 	.get_max_filters = can_loopback_get_max_filters,
381 	/* Recommended configuration ranges from CiA 601-2 */
382 	.timing_min = {
383 		.sjw = 1,
384 		.prop_seg = 0,
385 		.phase_seg1 = 2,
386 		.phase_seg2 = 2,
387 		.prescaler = 1
388 	},
389 	.timing_max = {
390 		.sjw = 128,
391 		.prop_seg = 0,
392 		.phase_seg1 = 256,
393 		.phase_seg2 = 128,
394 		.prescaler = 32
395 	},
396 #ifdef CONFIG_CAN_FD_MODE
397 	.set_timing_data = can_loopback_set_timing_data,
398 	/* Recommended configuration ranges from CiA 601-2 */
399 	.timing_data_min = {
400 		.sjw = 1,
401 		.prop_seg = 0,
402 		.phase_seg1 = 1,
403 		.phase_seg2 = 1,
404 		.prescaler = 1
405 	},
406 	.timing_data_max = {
407 		.sjw = 16,
408 		.prop_seg = 0,
409 		.phase_seg1 = 32,
410 		.phase_seg2 = 16,
411 		.prescaler = 32
412 	},
413 #endif /* CONFIG_CAN_FD_MODE */
414 };
415 
can_loopback_init(const struct device * dev)416 static int can_loopback_init(const struct device *dev)
417 {
418 	struct can_loopback_data *data = dev->data;
419 	k_tid_t tx_tid;
420 
421 	k_mutex_init(&data->mtx);
422 
423 	for (int i = 0; i < CONFIG_CAN_MAX_FILTER; i++) {
424 		data->filters[i].rx_cb = NULL;
425 	}
426 
427 	k_msgq_init(&data->tx_msgq, data->msgq_buffer, sizeof(struct can_loopback_frame),
428 		    CONFIG_CAN_LOOPBACK_TX_MSGQ_SIZE);
429 
430 	tx_tid = k_thread_create(&data->tx_thread_data, data->tx_thread_stack,
431 				 K_KERNEL_STACK_SIZEOF(data->tx_thread_stack),
432 				 tx_thread, (void *)dev, NULL, NULL,
433 				 CONFIG_CAN_LOOPBACK_TX_THREAD_PRIORITY,
434 				 0, K_NO_WAIT);
435 	if (!tx_tid) {
436 		LOG_ERR("ERROR spawning tx thread");
437 		return -1;
438 	}
439 
440 	k_thread_name_set(tx_tid, dev->name);
441 
442 	return 0;
443 }
444 
445 #ifdef CONFIG_CAN_FD_MODE
446 #define CAN_LOOPBACK_MAX_BITRATE 8000000
447 #else /* CONFIG_CAN_FD_MODE */
448 #define CAN_LOOPBACK_MAX_BITRATE 1000000
449 #endif /* !CONFIG_CAN_FD_MODE */
450 
451 #define CAN_LOOPBACK_INIT(inst)									\
452 	static const struct can_loopback_config can_loopback_config_##inst = {			\
453 		.common = CAN_DT_DRIVER_CONFIG_INST_GET(inst, 0, CAN_LOOPBACK_MAX_BITRATE),	\
454 	};											\
455 												\
456 	static struct can_loopback_data can_loopback_data_##inst;				\
457 												\
458 	CAN_DEVICE_DT_INST_DEFINE(inst, can_loopback_init, NULL,				\
459 				  &can_loopback_data_##inst,					\
460 				  &can_loopback_config_##inst,					\
461 				  POST_KERNEL, CONFIG_CAN_INIT_PRIORITY,			\
462 				  &can_loopback_driver_api);
463 
464 DT_INST_FOREACH_STATUS_OKAY(CAN_LOOPBACK_INIT)
465