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