1 /*
2  * Copyright (c) 2022 Martin Jäger <martin@libre.solar>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT zephyr_native_linux_can
8 
9 #include <stdbool.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <cmdline.h>
13 #include <posix_native_task.h>
14 
15 #include <zephyr/drivers/can.h>
16 #include <zephyr/kernel.h>
17 #include <zephyr/logging/log.h>
18 #include <zephyr/net/net_pkt.h>
19 #include <zephyr/net/socketcan.h>
20 #include <zephyr/net/socketcan_utils.h>
21 
22 #include "can_native_linux_adapt.h"
23 #include "nsi_host_trampolines.h"
24 
25 LOG_MODULE_REGISTER(can_native_linux, CONFIG_CAN_LOG_LEVEL);
26 
27 struct can_filter_context {
28 	can_rx_callback_t rx_cb;
29 	void *cb_arg;
30 	struct can_filter filter;
31 };
32 
33 struct can_native_linux_data {
34 	struct can_driver_data common;
35 	struct can_filter_context filters[CONFIG_CAN_MAX_FILTER];
36 	struct k_mutex filter_mutex;
37 	struct k_sem tx_idle;
38 	can_tx_callback_t tx_callback;
39 	void *tx_user_data;
40 	int dev_fd; /* Linux socket file descriptor */
41 	struct k_thread rx_thread;
42 
43 	K_KERNEL_STACK_MEMBER(rx_thread_stack, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE);
44 };
45 
46 struct can_native_linux_config {
47 	const struct can_driver_config common;
48 	const char *if_name;
49 };
50 
51 static const char *if_name_cmd_opt;
52 
dispatch_frame(const struct device * dev,struct can_frame * frame)53 static void dispatch_frame(const struct device *dev, struct can_frame *frame)
54 {
55 	struct can_native_linux_data *data = dev->data;
56 	can_rx_callback_t callback;
57 	struct can_frame tmp_frame;
58 
59 	k_mutex_lock(&data->filter_mutex, K_FOREVER);
60 
61 	for (int filter_id = 0; filter_id < ARRAY_SIZE(data->filters); filter_id++) {
62 		if (data->filters[filter_id].rx_cb == NULL) {
63 			continue;
64 		}
65 
66 		if (!can_frame_matches_filter(frame, &data->filters[filter_id].filter)) {
67 			continue;
68 		}
69 
70 		/* Make a temporary copy in case the user modifies the message */
71 		tmp_frame = *frame;
72 
73 		callback = data->filters[filter_id].rx_cb;
74 		callback(dev, &tmp_frame, data->filters[filter_id].cb_arg);
75 	}
76 
77 	k_mutex_unlock(&data->filter_mutex);
78 }
79 
rx_thread(void * arg1,void * arg2,void * arg3)80 static void rx_thread(void *arg1, void *arg2, void *arg3)
81 {
82 	const struct device *dev = arg1;
83 	struct can_native_linux_data *data = dev->data;
84 	struct socketcan_frame sframe;
85 	struct can_frame frame;
86 	bool msg_confirm;
87 	int count;
88 
89 	ARG_UNUSED(arg2);
90 	ARG_UNUSED(arg3);
91 
92 	LOG_DBG("Starting Linux SocketCAN RX thread");
93 
94 	while (true) {
95 		while (linux_socketcan_poll_data(data->dev_fd) == 0) {
96 			count = linux_socketcan_read_data(data->dev_fd, (void *)(&sframe),
97 							   sizeof(sframe), &msg_confirm);
98 			if (msg_confirm) {
99 				data->tx_callback(dev, 0, data->tx_user_data);
100 				k_sem_give(&data->tx_idle);
101 
102 				if ((data->common.mode & CAN_MODE_LOOPBACK) == 0U) {
103 					continue;
104 				}
105 			}
106 			if ((count <= 0) || !data->common.started) {
107 				break;
108 			}
109 
110 			socketcan_to_can_frame(&sframe, &frame);
111 
112 #ifndef CONFIG_CAN_ACCEPT_RTR
113 			if ((frame.flags & CAN_FRAME_RTR) != 0U) {
114 				continue;
115 			}
116 #endif /* !CONFIG_CAN_ACCEPT_RTR*/
117 
118 			LOG_DBG("Received %d bytes. Id: 0x%x, ID type: %s %s",
119 				frame.dlc, frame.id,
120 				(frame.flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
121 				(frame.flags & CAN_FRAME_RTR) != 0 ? ", RTR frame" : "");
122 
123 			dispatch_frame(dev, &frame);
124 		}
125 
126 		/* short sleep required to avoid blocking the whole native process */
127 		k_sleep(K_MSEC(1));
128 	}
129 }
130 
can_native_linux_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)131 static int can_native_linux_send(const struct device *dev, const struct can_frame *frame,
132 				 k_timeout_t timeout, can_tx_callback_t callback, void *user_data)
133 {
134 	struct can_native_linux_data *data = dev->data;
135 	struct socketcan_frame sframe;
136 	uint8_t max_dlc = CAN_MAX_DLC;
137 	size_t mtu = CAN_MTU;
138 	int ret = -EIO;
139 
140 	LOG_DBG("Sending %d bytes on %s. Id: 0x%x, ID type: %s %s",
141 		frame->dlc, dev->name, frame->id,
142 		(frame->flags & CAN_FRAME_IDE) != 0 ? "extended" : "standard",
143 		(frame->flags & CAN_FRAME_RTR) != 0 ? ", RTR frame" : "");
144 
145 #ifdef CONFIG_CAN_FD_MODE
146 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR |
147 		CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0) {
148 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
149 		return -ENOTSUP;
150 	}
151 
152 	if ((frame->flags & CAN_FRAME_FDF) != 0) {
153 		if ((data->common.mode & CAN_MODE_FD) == 0U) {
154 			return -ENOTSUP;
155 		}
156 
157 		max_dlc = CANFD_MAX_DLC;
158 		mtu = CANFD_MTU;
159 	}
160 #else /* CONFIG_CAN_FD_MODE */
161 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR)) != 0) {
162 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
163 		return -ENOTSUP;
164 	}
165 #endif /* !CONFIG_CAN_FD_MODE */
166 
167 	if (frame->dlc > max_dlc) {
168 		LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, max_dlc);
169 		return -EINVAL;
170 	}
171 
172 	if (data->dev_fd <= 0) {
173 		LOG_ERR("No file descriptor: %d", data->dev_fd);
174 		return -EIO;
175 	}
176 
177 	if (!data->common.started) {
178 		return -ENETDOWN;
179 	}
180 
181 	socketcan_from_can_frame(frame, &sframe);
182 
183 	if (k_sem_take(&data->tx_idle, timeout) != 0) {
184 		return -EAGAIN;
185 	}
186 
187 	data->tx_callback = callback;
188 	data->tx_user_data = user_data;
189 
190 	ret = nsi_host_write(data->dev_fd, &sframe, mtu);
191 	if (ret < 0) {
192 		LOG_ERR("Cannot send CAN data len %d (%d)", sframe.len, -errno);
193 	}
194 
195 	return 0;
196 }
197 
can_native_linux_add_rx_filter(const struct device * dev,can_rx_callback_t cb,void * cb_arg,const struct can_filter * filter)198 static int can_native_linux_add_rx_filter(const struct device *dev, can_rx_callback_t cb,
199 					  void *cb_arg, const struct can_filter *filter)
200 {
201 	struct can_native_linux_data *data = dev->data;
202 	struct can_filter_context *filter_ctx;
203 	int filter_id = -ENOSPC;
204 
205 	LOG_DBG("Setting filter ID: 0x%x, mask: 0x%x", filter->id,
206 		filter->mask);
207 
208 	if ((filter->flags & ~(CAN_FILTER_IDE)) != 0) {
209 		LOG_ERR("unsupported CAN filter flags 0x%02x", filter->flags);
210 		return -ENOTSUP;
211 	}
212 
213 	k_mutex_lock(&data->filter_mutex, K_FOREVER);
214 
215 	for (int i = 0; i < ARRAY_SIZE(data->filters); i++) {
216 		if (data->filters[i].rx_cb == NULL) {
217 			filter_id = i;
218 			break;
219 		}
220 	}
221 
222 	if (filter_id < 0) {
223 		LOG_ERR("No free filter left");
224 		k_mutex_unlock(&data->filter_mutex);
225 		return filter_id;
226 	}
227 
228 	filter_ctx = &data->filters[filter_id];
229 	filter_ctx->rx_cb = cb;
230 	filter_ctx->cb_arg = cb_arg;
231 	filter_ctx->filter = *filter;
232 
233 	k_mutex_unlock(&data->filter_mutex);
234 
235 	LOG_DBG("Filter added. ID: %d", filter_id);
236 
237 	return filter_id;
238 }
239 
can_native_linux_remove_rx_filter(const struct device * dev,int filter_id)240 static void can_native_linux_remove_rx_filter(const struct device *dev, int filter_id)
241 {
242 	struct can_native_linux_data *data = dev->data;
243 
244 	if (filter_id < 0 || filter_id >= ARRAY_SIZE(data->filters)) {
245 		LOG_ERR("filter ID %d out of bounds", filter_id);
246 		return;
247 	}
248 
249 	k_mutex_lock(&data->filter_mutex, K_FOREVER);
250 	data->filters[filter_id].rx_cb = NULL;
251 	k_mutex_unlock(&data->filter_mutex);
252 
253 	LOG_DBG("Filter removed. ID: %d", filter_id);
254 }
255 
can_native_linux_get_capabilities(const struct device * dev,can_mode_t * cap)256 static int can_native_linux_get_capabilities(const struct device *dev, can_mode_t *cap)
257 {
258 	ARG_UNUSED(dev);
259 
260 	*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK;
261 
262 #if CONFIG_CAN_FD_MODE
263 	*cap |= CAN_MODE_FD;
264 #endif /* CONFIG_CAN_FD_MODE */
265 
266 	return 0;
267 }
268 
can_native_linux_start(const struct device * dev)269 static int can_native_linux_start(const struct device *dev)
270 {
271 	struct can_native_linux_data *data = dev->data;
272 
273 	if (data->common.started) {
274 		return -EALREADY;
275 	}
276 
277 	data->common.started = true;
278 
279 	return 0;
280 }
281 
can_native_linux_stop(const struct device * dev)282 static int can_native_linux_stop(const struct device *dev)
283 {
284 	struct can_native_linux_data *data = dev->data;
285 
286 	if (!data->common.started) {
287 		return -EALREADY;
288 	}
289 
290 	data->common.started = false;
291 
292 	return 0;
293 }
294 
can_native_linux_set_mode(const struct device * dev,can_mode_t mode)295 static int can_native_linux_set_mode(const struct device *dev, can_mode_t mode)
296 {
297 	struct can_native_linux_data *data = dev->data;
298 	int err;
299 
300 #ifdef CONFIG_CAN_FD_MODE
301 	if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_FD)) != 0) {
302 		LOG_ERR("unsupported mode: 0x%08x", mode);
303 		return -ENOTSUP;
304 	}
305 #else
306 	if ((mode & ~(CAN_MODE_LOOPBACK)) != 0) {
307 		LOG_ERR("unsupported mode: 0x%08x", mode);
308 		return -ENOTSUP;
309 	}
310 #endif /* CONFIG_CAN_FD_MODE */
311 
312 	if (data->common.started) {
313 		return -EBUSY;
314 	}
315 
316 	err = linux_socketcan_set_mode_fd(data->dev_fd, (mode & CAN_MODE_FD) != 0);
317 	if (err != 0) {
318 		LOG_ERR("failed to set mode");
319 		return -EIO;
320 	}
321 
322 	data->common.mode = mode;
323 
324 	return 0;
325 }
326 
can_native_linux_set_timing(const struct device * dev,const struct can_timing * timing)327 static int can_native_linux_set_timing(const struct device *dev, const struct can_timing *timing)
328 {
329 	struct can_native_linux_data *data = dev->data;
330 
331 	ARG_UNUSED(timing);
332 
333 	if (data->common.started) {
334 		return -EBUSY;
335 	}
336 
337 	return 0;
338 }
339 
340 #ifdef CONFIG_CAN_FD_MODE
can_native_linux_set_timing_data(const struct device * dev,const struct can_timing * timing)341 static int can_native_linux_set_timing_data(const struct device *dev,
342 					    const struct can_timing *timing)
343 {
344 	struct can_native_linux_data *data = dev->data;
345 
346 	ARG_UNUSED(timing);
347 
348 	if (data->common.started) {
349 		return -EBUSY;
350 	}
351 
352 	return 0;
353 }
354 #endif /* CONFIG_CAN_FD_MODE */
355 
can_native_linux_get_state(const struct device * dev,enum can_state * state,struct can_bus_err_cnt * err_cnt)356 static int can_native_linux_get_state(const struct device *dev, enum can_state *state,
357 				      struct can_bus_err_cnt *err_cnt)
358 {
359 	struct can_native_linux_data *data = dev->data;
360 
361 	if (state != NULL) {
362 		if (!data->common.started) {
363 			*state = CAN_STATE_STOPPED;
364 		} else {
365 			/* SocketCAN does not forward error frames by default */
366 			*state = CAN_STATE_ERROR_ACTIVE;
367 		}
368 	}
369 
370 	if (err_cnt) {
371 		err_cnt->tx_err_cnt = 0;
372 		err_cnt->rx_err_cnt = 0;
373 	}
374 
375 	return 0;
376 }
377 
can_native_linux_set_state_change_callback(const struct device * dev,can_state_change_callback_t cb,void * user_data)378 static void can_native_linux_set_state_change_callback(const struct device *dev,
379 						       can_state_change_callback_t cb,
380 						       void *user_data)
381 {
382 	ARG_UNUSED(dev);
383 	ARG_UNUSED(cb);
384 	ARG_UNUSED(user_data);
385 }
386 
can_native_linux_get_core_clock(const struct device * dev,uint32_t * rate)387 static int can_native_linux_get_core_clock(const struct device *dev, uint32_t *rate)
388 {
389 	/* Return 16MHz as an realistic value for the testcases */
390 	*rate = 16000000;
391 
392 	return 0;
393 }
394 
can_native_linux_get_max_filters(const struct device * dev,bool ide)395 static int can_native_linux_get_max_filters(const struct device *dev, bool ide)
396 {
397 	ARG_UNUSED(ide);
398 
399 	return CONFIG_CAN_MAX_FILTER;
400 }
401 
402 static DEVICE_API(can, can_native_linux_driver_api) = {
403 	.start = can_native_linux_start,
404 	.stop = can_native_linux_stop,
405 	.get_capabilities = can_native_linux_get_capabilities,
406 	.set_mode = can_native_linux_set_mode,
407 	.set_timing = can_native_linux_set_timing,
408 	.send = can_native_linux_send,
409 	.add_rx_filter = can_native_linux_add_rx_filter,
410 	.remove_rx_filter = can_native_linux_remove_rx_filter,
411 	.get_state = can_native_linux_get_state,
412 	.set_state_change_callback = can_native_linux_set_state_change_callback,
413 	.get_core_clock = can_native_linux_get_core_clock,
414 	.get_max_filters = can_native_linux_get_max_filters,
415 	.timing_min = {
416 		.sjw = 0x1,
417 		.prop_seg = 0x01,
418 		.phase_seg1 = 0x01,
419 		.phase_seg2 = 0x01,
420 		.prescaler = 0x01
421 	},
422 	.timing_max = {
423 		.sjw = 0x0F,
424 		.prop_seg = 0x0F,
425 		.phase_seg1 = 0x0F,
426 		.phase_seg2 = 0x0F,
427 		.prescaler = 0xFFFF
428 	},
429 #ifdef CONFIG_CAN_FD_MODE
430 	.set_timing_data = can_native_linux_set_timing_data,
431 	.timing_data_min = {
432 		.sjw = 0x1,
433 		.prop_seg = 0x01,
434 		.phase_seg1 = 0x01,
435 		.phase_seg2 = 0x01,
436 		.prescaler = 0x01
437 	},
438 	.timing_data_max = {
439 		.sjw = 0x0F,
440 		.prop_seg = 0x0F,
441 		.phase_seg1 = 0x0F,
442 		.phase_seg2 = 0x0F,
443 		.prescaler = 0xFFFF
444 	},
445 #endif /* CONFIG_CAN_FD_MODE */
446 };
447 
can_native_linux_init(const struct device * dev)448 static int can_native_linux_init(const struct device *dev)
449 {
450 	const struct can_native_linux_config *cfg = dev->config;
451 	struct can_native_linux_data *data = dev->data;
452 	const char *if_name;
453 
454 	k_mutex_init(&data->filter_mutex);
455 	k_sem_init(&data->tx_idle, 1, 1);
456 
457 	if (if_name_cmd_opt != NULL) {
458 		if_name = if_name_cmd_opt;
459 	} else {
460 		if_name = cfg->if_name;
461 	}
462 
463 	LOG_DBG("Opening %s", if_name);
464 	data->dev_fd = linux_socketcan_iface_open(if_name);
465 	if (data->dev_fd < 0) {
466 		LOG_ERR("Cannot open %s (%d)", if_name, data->dev_fd);
467 		return -ENODEV;
468 	}
469 
470 	k_thread_create(&data->rx_thread, data->rx_thread_stack,
471 			K_KERNEL_STACK_SIZEOF(data->rx_thread_stack),
472 			rx_thread, (void *)dev, NULL, NULL,
473 			CONFIG_CAN_NATIVE_LINUX_RX_THREAD_PRIORITY,
474 			0, K_NO_WAIT);
475 
476 	LOG_DBG("Init of %s done", dev->name);
477 
478 	return 0;
479 }
480 
481 #define CAN_NATIVE_LINUX_INIT(inst)						\
482 										\
483 static const struct can_native_linux_config can_native_linux_cfg_##inst = {	\
484 	.common = CAN_DT_DRIVER_CONFIG_INST_GET(inst, 0, 0),			\
485 	.if_name = DT_INST_PROP(inst, host_interface),				\
486 };										\
487 										\
488 static struct can_native_linux_data can_native_linux_data_##inst;		\
489 										\
490 CAN_DEVICE_DT_INST_DEFINE(inst, can_native_linux_init, NULL,			\
491 			  &can_native_linux_data_##inst,			\
492 			  &can_native_linux_cfg_##inst,				\
493 			  POST_KERNEL, CONFIG_CAN_INIT_PRIORITY,		\
494 			  &can_native_linux_driver_api);
495 
DT_INST_FOREACH_STATUS_OKAY(CAN_NATIVE_LINUX_INIT)496 DT_INST_FOREACH_STATUS_OKAY(CAN_NATIVE_LINUX_INIT)
497 
498 static void add_native_options(void)
499 {
500 	static struct args_struct_t can_native_options[] = {
501 		{
502 			.is_mandatory = false,
503 			.option = "can-if",
504 			.name = "name",
505 			.type = 's',
506 			.dest = (void *)&if_name_cmd_opt,
507 			.descript = "Name of the host CAN interface to use",
508 		},
509 		ARG_TABLE_ENDMARKER,
510 	};
511 
512 	native_add_command_line_opts(can_native_options);
513 }
514 
515 NATIVE_TASK(add_native_options, PRE_BOOT_1, 10);
516