1 /*
2 * Copyright (c) 2018 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_socket_can_sample, LOG_LEVEL_DBG);
9
10 #include <zephyr/kernel.h>
11
12 #include <zephyr/drivers/can.h>
13 #include <zephyr/net/socket.h>
14 #include <zephyr/net/socketcan.h>
15 #include <zephyr/net/socketcan_utils.h>
16
17 #define PRIORITY k_thread_priority_get(k_current_get())
18 #define STACKSIZE 1024
19 #define SLEEP_PERIOD K_SECONDS(1)
20
21 static k_tid_t tx_tid;
22 static K_THREAD_STACK_DEFINE(tx_stack, STACKSIZE);
23 static struct k_thread tx_data;
24
25 /* For testing purposes, we create another RX receiver if configured so */
26 #if CONFIG_NET_SOCKETS_CAN_RECEIVERS == 2
27 static k_tid_t rx_tid;
28 static K_THREAD_STACK_DEFINE(rx_stack, STACKSIZE);
29 static struct k_thread rx_data;
30 #endif
31
32 #define CLOSE_PERIOD 15
33
34 static const struct can_filter zfilter = {
35 .flags = 0U,
36 .id = 0x1,
37 .mask = CAN_STD_ID_MASK
38 };
39
40 static struct socketcan_filter sock_filter;
41
tx(void * p1,void * p2,void * p3)42 static void tx(void *p1, void *p2, void *p3)
43 {
44 ARG_UNUSED(p2);
45 ARG_UNUSED(p3);
46
47 int *can_fd = p1;
48 int fd = POINTER_TO_INT(can_fd);
49 struct can_frame zframe = {0};
50 struct socketcan_frame sframe = {0};
51 int ret, i;
52
53 zframe.id = 0x1;
54 zframe.dlc = 8U;
55
56 for (i = 0; i < zframe.dlc; i++) {
57 zframe.data[i] = 0xF0 | i;
58 }
59
60 socketcan_from_can_frame(&zframe, &sframe);
61
62 LOG_DBG("Sending CAN data...");
63
64 while (1) {
65 ret = send(fd, &sframe, sizeof(sframe), 0);
66 if (ret < 0) {
67 LOG_ERR("Cannot send CAN frame (%d)", -errno);
68 }
69
70 k_sleep(SLEEP_PERIOD);
71 }
72 }
73
create_socket(const struct socketcan_filter * sfilter)74 static int create_socket(const struct socketcan_filter *sfilter)
75 {
76 struct sockaddr_can can_addr;
77 int fd, ret;
78
79 fd = socket(AF_CAN, SOCK_RAW, CAN_RAW);
80 if (fd < 0) {
81 LOG_ERR("Cannot create %s CAN socket (%d)", "2nd", fd);
82 return fd;
83 }
84
85 can_addr.can_ifindex = net_if_get_by_iface(
86 net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS_RAW)));
87 can_addr.can_family = PF_CAN;
88
89 ret = bind(fd, (struct sockaddr *)&can_addr, sizeof(can_addr));
90 if (ret < 0) {
91 LOG_ERR("Cannot bind %s CAN socket (%d)", "2nd", -errno);
92 (void)close(fd);
93 return ret;
94 }
95
96 (void)setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, sfilter,
97 sizeof(*sfilter));
98
99 return fd;
100 }
101
rx(void * p1,void * p2,void * p3)102 static void rx(void *p1, void *p2, void *p3)
103 {
104 int *can_fd = p1;
105 int *do_close_period = p2;
106 const struct socketcan_filter *sfilter = p3;
107 int close_period = POINTER_TO_INT(do_close_period);
108 int fd = POINTER_TO_INT(can_fd);
109 struct sockaddr_can can_addr;
110 socklen_t addr_len;
111 struct can_frame zframe;
112 struct socketcan_frame sframe;
113 int ret;
114
115 LOG_DBG("[%d] Waiting CAN data...", fd);
116
117 while (1) {
118 uint8_t *data;
119
120 memset(&sframe, 0, sizeof(sframe));
121 addr_len = sizeof(can_addr);
122
123 ret = recvfrom(fd, &sframe, sizeof(struct socketcan_frame),
124 0, (struct sockaddr *)&can_addr, &addr_len);
125 if (ret < 0) {
126 LOG_ERR("[%d] Cannot receive CAN frame (%d)", fd,
127 -errno);
128 continue;
129 }
130
131 socketcan_to_can_frame(&sframe, &zframe);
132
133 LOG_INF("[%d] CAN frame: IDE 0x%x RTR 0x%x ID 0x%x DLC 0x%x",
134 fd,
135 (zframe.flags & CAN_FRAME_IDE) != 0 ? 1 : 0,
136 (zframe.flags & CAN_FRAME_RTR) != 0 ? 1 : 0,
137 zframe.id, zframe.dlc);
138
139 if ((zframe.flags & CAN_FRAME_RTR) != 0) {
140 LOG_INF("[%d] EXT Remote frame received", fd);
141 } else {
142 if (zframe.dlc > 8) {
143 data = (uint8_t *)zframe.data_32;
144 } else {
145 data = zframe.data;
146 }
147
148 LOG_HEXDUMP_INF(data, zframe.dlc, "Data");
149 }
150
151 if (POINTER_TO_INT(do_close_period) > 0) {
152 close_period--;
153 if (close_period <= 0) {
154 (void)close(fd);
155
156 k_sleep(K_SECONDS(1));
157
158 fd = create_socket(sfilter);
159 if (fd < 0) {
160 LOG_ERR("Cannot get socket (%d)",
161 -errno);
162 return;
163 }
164
165 close_period = POINTER_TO_INT(do_close_period);
166 }
167 }
168 }
169 }
170
setup_socket(void)171 static int setup_socket(void)
172 {
173 struct sockaddr_can can_addr;
174 struct net_if *iface;
175 int fd, rx_fd;
176 int ret;
177
178 socketcan_from_can_filter(&zfilter, &sock_filter);
179
180 iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS_RAW));
181 if (!iface) {
182 LOG_ERR("No CANBUS network interface found!");
183 return -ENOENT;
184 }
185
186 fd = socket(AF_CAN, SOCK_RAW, CAN_RAW);
187 if (fd < 0) {
188 ret = -errno;
189 LOG_ERR("Cannot create %s CAN socket (%d)", "1st", ret);
190 return ret;
191 }
192
193 can_addr.can_ifindex = net_if_get_by_iface(iface);
194 can_addr.can_family = PF_CAN;
195
196 ret = bind(fd, (struct sockaddr *)&can_addr, sizeof(can_addr));
197 if (ret < 0) {
198 ret = -errno;
199 LOG_ERR("Cannot bind %s CAN socket (%d)", "1st", ret);
200 goto cleanup;
201 }
202
203 ret = setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &sock_filter,
204 sizeof(sock_filter));
205 if (ret < 0) {
206 ret = -errno;
207 LOG_ERR("Cannot set CAN sockopt (%d)", ret);
208 goto cleanup;
209 }
210
211 /* Delay TX startup so that RX is ready to receive */
212 tx_tid = k_thread_create(&tx_data, tx_stack,
213 K_THREAD_STACK_SIZEOF(tx_stack),
214 tx, INT_TO_POINTER(fd),
215 NULL, NULL, PRIORITY, 0, K_SECONDS(1));
216 if (!tx_tid) {
217 ret = -ENOENT;
218 errno = -ret;
219 LOG_ERR("Cannot create TX thread!");
220 goto cleanup;
221 }
222
223 LOG_DBG("Started socket CAN TX thread");
224
225 LOG_INF("1st RX fd %d", fd);
226
227 rx_fd = fd;
228
229 #if CONFIG_NET_SOCKETS_CAN_RECEIVERS == 2
230 fd = create_socket(&sock_filter);
231 if (fd >= 0) {
232 rx_tid = k_thread_create(&rx_data, rx_stack,
233 K_THREAD_STACK_SIZEOF(rx_stack),
234 rx,
235 INT_TO_POINTER(fd),
236 INT_TO_POINTER(CLOSE_PERIOD),
237 &sock_filter, PRIORITY, 0, K_NO_WAIT);
238 if (!rx_tid) {
239 ret = -ENOENT;
240 errno = -ret;
241 LOG_ERR("Cannot create 2nd RX thread!");
242 goto cleanup2;
243 }
244
245 LOG_INF("2nd RX fd %d", fd);
246 } else {
247 LOG_ERR("2nd RX not created (%d)", fd);
248 }
249 #endif
250
251 return rx_fd;
252
253 #if CONFIG_NET_SOCKETS_CAN_RECEIVERS == 2
254 cleanup2:
255 (void)close(rx_fd);
256 #endif
257
258 cleanup:
259 (void)close(fd);
260 return ret;
261 }
262
main(void)263 int main(void)
264 {
265 const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
266 int ret;
267 int fd;
268
269 #ifdef CONFIG_SAMPLE_SOCKETCAN_LOOPBACK_MODE
270 ret = can_set_mode(dev, CAN_MODE_LOOPBACK);
271 if (ret != 0) {
272 LOG_ERR("Cannot set CAN loopback mode (%d)", ret);
273 return 0;
274 }
275 #endif
276
277 ret = can_start(dev);
278 if (ret != 0) {
279 LOG_ERR("Cannot start CAN controller (%d)", ret);
280 return 0;
281 }
282
283 /* Let the device start before doing anything */
284 k_sleep(K_SECONDS(2));
285
286 fd = setup_socket();
287 if (fd < 0) {
288 LOG_ERR("Cannot start CAN application (%d)", fd);
289 return 0;
290 }
291
292 rx(INT_TO_POINTER(fd), NULL, NULL);
293 return 0;
294 }
295