1 /*
2  * Copyright (c) 2016-2019 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief App implementing 802.15.4 "serial-radio" protocol
10  *
11  * Application implementing 802.15.4 "serial-radio" protocol compatible
12  * with popular Contiki-based native border routers.
13  */
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(wpan_serial, CONFIG_USB_DEVICE_LOG_LEVEL);
17 
18 #include <zephyr/drivers/uart.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/usb/usb_device.h>
21 #include <zephyr/random/random.h>
22 
23 #include <zephyr/net/buf.h>
24 #include <net_private.h>
25 #include <zephyr/net/ieee802154_radio.h>
26 
27 #if defined(CONFIG_NET_TC_THREAD_COOPERATIVE)
28 #define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1)
29 #else
30 #define THREAD_PRIORITY K_PRIO_PREEMPT(8)
31 #endif
32 
33 #define SLIP_END     0300
34 #define SLIP_ESC     0333
35 #define SLIP_ESC_END 0334
36 #define SLIP_ESC_ESC 0335
37 
38 enum slip_state {
39 	STATE_GARBAGE,
40 	STATE_OK,
41 	STATE_ESC,
42 };
43 
44 /* RX queue */
45 static struct k_fifo rx_queue;
46 static K_THREAD_STACK_DEFINE(rx_stack, 1024);
47 static struct k_thread rx_thread_data;
48 
49 /* TX queue */
50 static struct k_fifo tx_queue;
51 static K_THREAD_STACK_DEFINE(tx_stack, 1024);
52 static struct k_thread tx_thread_data;
53 
54 /* Buffer for SLIP encoded data for the worst case */
55 static uint8_t slip_buf[1 + 2 * CONFIG_NET_BUF_DATA_SIZE];
56 
57 /* ieee802.15.4 device */
58 static struct ieee802154_radio_api *radio_api;
59 static const struct device *const ieee802154_dev =
60 	DEVICE_DT_GET(DT_CHOSEN(zephyr_ieee802154));
61 uint8_t mac_addr[8]; /* in little endian */
62 
63 /* UART device */
64 static const struct device *const uart_dev =
65 	DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart);
66 
67 /* SLIP state machine */
68 static uint8_t slip_state = STATE_OK;
69 
70 static struct net_pkt *pkt_curr;
71 
72 /* General helpers */
73 
slip_process_byte(unsigned char c)74 static int slip_process_byte(unsigned char c)
75 {
76 	struct net_buf *buf;
77 #ifdef VERBOSE_DEBUG
78 	LOG_DBG("recv: state %u byte %x", slip_state, c);
79 #endif
80 	switch (slip_state) {
81 	case STATE_GARBAGE:
82 		if (c == SLIP_END) {
83 			slip_state = STATE_OK;
84 		}
85 		LOG_DBG("garbage: discard byte %x", c);
86 		return 0;
87 
88 	case STATE_ESC:
89 		if (c == SLIP_ESC_END) {
90 			c = SLIP_END;
91 		} else if (c == SLIP_ESC_ESC) {
92 			c = SLIP_ESC;
93 		} else {
94 			slip_state = STATE_GARBAGE;
95 			return 0;
96 		}
97 		slip_state = STATE_OK;
98 		break;
99 
100 	case STATE_OK:
101 		if (c == SLIP_ESC) {
102 			slip_state = STATE_ESC;
103 			return 0;
104 		} else if (c == SLIP_END) {
105 			return 1;
106 		}
107 		break;
108 	}
109 
110 #ifdef VERBOSE_DEBUG
111 	LOG_DBG("processed: state %u byte %x", slip_state, c);
112 #endif
113 
114 	if (!pkt_curr) {
115 		pkt_curr = net_pkt_rx_alloc_with_buffer(NULL, 256,
116 							AF_UNSPEC, 0,
117 							K_NO_WAIT);
118 		if (!pkt_curr) {
119 			LOG_ERR("No more buffers");
120 			return 0;
121 		}
122 	}
123 
124 	buf = net_buf_frag_last(pkt_curr->buffer);
125 	if (!net_buf_tailroom(buf)) {
126 		LOG_ERR("No more buf space: buf %p len %u", buf, buf->len);
127 
128 		net_pkt_unref(pkt_curr);
129 		pkt_curr = NULL;
130 		return 0;
131 	}
132 
133 	net_buf_add_u8(buf, c);
134 
135 	return 0;
136 }
137 
interrupt_handler(const struct device * dev,void * user_data)138 static void interrupt_handler(const struct device *dev, void *user_data)
139 {
140 	ARG_UNUSED(user_data);
141 
142 	while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {
143 		unsigned char byte;
144 
145 		if (!uart_irq_rx_ready(dev)) {
146 			continue;
147 		}
148 
149 		while (uart_fifo_read(dev, &byte, sizeof(byte))) {
150 			if (slip_process_byte(byte)) {
151 				/**
152 				 * slip_process_byte() returns 1 on
153 				 * SLIP_END, even after receiving full
154 				 * packet
155 				 */
156 				if (!pkt_curr) {
157 					LOG_DBG("Skip SLIP_END");
158 					continue;
159 				}
160 
161 				LOG_DBG("Full packet %p, len %u", pkt_curr,
162 					net_pkt_get_len(pkt_curr));
163 
164 				k_fifo_put(&rx_queue, pkt_curr);
165 				pkt_curr = NULL;
166 			}
167 		}
168 	}
169 }
170 
171 /* Allocate and send data to USB Host */
send_data(uint8_t * cfg,uint8_t * data,size_t len)172 static void send_data(uint8_t *cfg, uint8_t *data, size_t len)
173 {
174 	struct net_pkt *pkt;
175 
176 	pkt = net_pkt_alloc_with_buffer(NULL, len + 5,
177 					AF_UNSPEC, 0, K_NO_WAIT);
178 	if (!pkt) {
179 		LOG_DBG("No pkt available");
180 		return;
181 	}
182 
183 	LOG_DBG("queue pkt %p len %u", pkt, len);
184 
185 	/* Add configuration id */
186 	net_pkt_write(pkt, cfg, 2);
187 	net_pkt_write(pkt, data, len);
188 
189 	/* simulate LQI */
190 	net_pkt_skip(pkt, 1);
191 	/* simulate FCS */
192 	net_pkt_skip(pkt, 2);
193 
194 	net_pkt_set_overwrite(pkt, true);
195 
196 	k_fifo_put(&tx_queue, pkt);
197 }
198 
get_ieee_addr(void)199 static void get_ieee_addr(void)
200 {
201 	uint8_t cfg[2] = { '!', 'M' };
202 	uint8_t mac[8];
203 
204 	LOG_DBG("");
205 
206 	/* Send in BE */
207 	sys_memcpy_swap(mac, mac_addr, sizeof(mac));
208 
209 	send_data(cfg, mac, sizeof(mac));
210 }
211 
process_request(struct net_buf * buf)212 static void process_request(struct net_buf *buf)
213 {
214 	uint8_t cmd = net_buf_pull_u8(buf);
215 
216 
217 	switch (cmd) {
218 	case 'M':
219 		get_ieee_addr();
220 		break;
221 	default:
222 		LOG_ERR("Not handled request %c", cmd);
223 		break;
224 	}
225 }
226 
send_pkt_report(uint8_t seq,uint8_t status,uint8_t num_tx)227 static void send_pkt_report(uint8_t seq, uint8_t status, uint8_t num_tx)
228 {
229 	uint8_t cfg[2] = { '!', 'R' };
230 	uint8_t report[3];
231 
232 	report[0] = seq;
233 	report[1] = status;
234 	report[2] = num_tx;
235 
236 	send_data(cfg, report, sizeof(report));
237 }
238 
process_data(struct net_pkt * pkt)239 static void process_data(struct net_pkt *pkt)
240 {
241 	struct net_buf *buf = net_buf_frag_last(pkt->buffer);
242 	uint8_t seq, num_attr;
243 	int ret, i;
244 
245 	seq = net_buf_pull_u8(buf);
246 	num_attr = net_buf_pull_u8(buf);
247 
248 	LOG_DBG("seq %u num_attr %u", seq, num_attr);
249 
250 	/**
251 	 * There are some attributes sent over this protocol
252 	 * discard them and return packet data report.
253 	 */
254 
255 	for (i = 0; i < num_attr; i++) {
256 		/* attr */
257 		net_buf_pull_u8(buf);
258 		/* value */
259 		net_buf_pull_be16(buf);
260 	}
261 
262 	/* Transmit data through radio */
263 	ret = radio_api->tx(ieee802154_dev, IEEE802154_TX_MODE_DIRECT,
264 			    pkt, buf);
265 	if (ret) {
266 		LOG_ERR("Error transmit data");
267 	}
268 
269 	/* TODO: Return correct status codes */
270 	/* TODO: Implement re-transmissions if needed */
271 
272 	/* Send packet data report */
273 	send_pkt_report(seq, ret, 1);
274 }
275 
set_channel(uint8_t chan)276 static void set_channel(uint8_t chan)
277 {
278 	LOG_DBG("Set channel %u", chan);
279 
280 	radio_api->set_channel(ieee802154_dev, chan);
281 }
282 
process_config(struct net_pkt * pkt)283 static void process_config(struct net_pkt *pkt)
284 {
285 	struct net_buf *buf = net_buf_frag_last(pkt->buffer);
286 	uint8_t cmd = net_buf_pull_u8(buf);
287 
288 	LOG_DBG("Process config %c", cmd);
289 
290 	switch (cmd) {
291 	case 'S':
292 		process_data(pkt);
293 		break;
294 	case 'C':
295 		set_channel(net_buf_pull_u8(buf));
296 		break;
297 	default:
298 		LOG_ERR("Unhandled cmd %u", cmd);
299 	}
300 }
301 
rx_thread(void * p1,void * p2,void * p3)302 static void rx_thread(void *p1, void *p2, void *p3)
303 {
304 	ARG_UNUSED(p1);
305 	ARG_UNUSED(p2);
306 	ARG_UNUSED(p3);
307 
308 	LOG_DBG("RX thread started");
309 
310 	while (true) {
311 		struct net_pkt *pkt;
312 		struct net_buf *buf;
313 		uint8_t specifier;
314 
315 		pkt = k_fifo_get(&rx_queue, K_FOREVER);
316 		buf = net_buf_frag_last(pkt->buffer);
317 
318 		LOG_DBG("rx_queue pkt %p buf %p", pkt, buf);
319 
320 		LOG_HEXDUMP_DBG(buf->data, buf->len, "SLIP >");
321 
322 		/* TODO: process */
323 		specifier = net_buf_pull_u8(buf);
324 		switch (specifier) {
325 		case '?':
326 			process_request(buf);
327 			break;
328 		case '!':
329 			process_config(pkt);
330 			break;
331 		default:
332 			LOG_ERR("Unknown message specifier %c", specifier);
333 			break;
334 		}
335 
336 		net_pkt_unref(pkt);
337 	}
338 }
339 
slip_buffer(uint8_t * sbuf,struct net_buf * buf)340 static size_t slip_buffer(uint8_t *sbuf, struct net_buf *buf)
341 {
342 	size_t len = buf->len;
343 	uint8_t *sbuf_orig = sbuf;
344 	int i;
345 
346 	/**
347 	 * This strange protocol does not require send START
348 	 * *sbuf++ = SLIP_END;
349 	 */
350 
351 	for (i = 0; i < len; i++) {
352 		uint8_t byte = net_buf_pull_u8(buf);
353 
354 		switch (byte) {
355 		case SLIP_END:
356 			*sbuf++ = SLIP_ESC;
357 			*sbuf++ = SLIP_ESC_END;
358 			break;
359 		case SLIP_ESC:
360 			*sbuf++ = SLIP_ESC;
361 			*sbuf++ = SLIP_ESC_ESC;
362 			break;
363 		default:
364 			*sbuf++ = byte;
365 		}
366 	}
367 
368 	*sbuf++ = SLIP_END;
369 
370 	return sbuf - sbuf_orig;
371 }
372 
try_write(uint8_t * data,uint16_t len)373 static int try_write(uint8_t *data, uint16_t len)
374 {
375 	int wrote;
376 
377 	while (len) {
378 		wrote = uart_fifo_fill(uart_dev, data, len);
379 		if (wrote <= 0) {
380 			return wrote;
381 		}
382 
383 		len -= wrote;
384 		data += wrote;
385 	}
386 
387 	return 0;
388 }
389 
390 /**
391  * TX - transmit to SLIP interface
392  */
tx_thread(void * p1,void * p2,void * p3)393 static void tx_thread(void *p1, void *p2, void *p3)
394 {
395 	ARG_UNUSED(p1);
396 	ARG_UNUSED(p2);
397 	ARG_UNUSED(p3);
398 
399 	LOG_DBG("TX thread started");
400 
401 	while (true) {
402 		struct net_pkt *pkt;
403 		struct net_buf *buf;
404 		size_t len;
405 
406 		pkt = k_fifo_get(&tx_queue, K_FOREVER);
407 		buf = net_buf_frag_last(pkt->buffer);
408 		len = net_pkt_get_len(pkt);
409 
410 		LOG_DBG("Send pkt %p buf %p len %d", pkt, buf, len);
411 
412 		LOG_HEXDUMP_DBG(buf->data, buf->len, "SLIP <");
413 
414 		/* remove FCS 2 bytes */
415 		buf->len -= 2U;
416 
417 		/* SLIP encode and send */
418 		len = slip_buffer(slip_buf, buf);
419 
420 		try_write(slip_buf, len);
421 
422 		net_pkt_unref(pkt);
423 	}
424 }
425 
init_rx_queue(void)426 static void init_rx_queue(void)
427 {
428 	k_fifo_init(&rx_queue);
429 
430 	k_thread_create(&rx_thread_data, rx_stack,
431 			K_THREAD_STACK_SIZEOF(rx_stack),
432 			rx_thread,
433 			NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT);
434 }
435 
init_tx_queue(void)436 static void init_tx_queue(void)
437 {
438 	k_fifo_init(&tx_queue);
439 
440 	k_thread_create(&tx_thread_data, tx_stack,
441 			K_THREAD_STACK_SIZEOF(tx_stack),
442 			tx_thread,
443 			NULL, NULL, NULL, THREAD_PRIORITY, 0, K_NO_WAIT);
444 }
445 
446 /**
447  * FIXME choose correct OUI, or add support in L2
448  */
get_mac(const struct device * dev)449 static uint8_t *get_mac(const struct device *dev)
450 {
451 	mac_addr[7] = 0x00;
452 	mac_addr[6] = 0x12;
453 	mac_addr[5] = 0x4b;
454 	mac_addr[4] = 0x00;
455 
456 	sys_rand_get(mac_addr, 4U);
457 
458 	mac_addr[0] = (mac_addr[0] & ~0x01) | 0x02;
459 
460 	return mac_addr;
461 }
462 
init_ieee802154(void)463 static bool init_ieee802154(void)
464 {
465 	LOG_INF("Initialize ieee802.15.4");
466 
467 	if (!device_is_ready(ieee802154_dev)) {
468 		LOG_ERR("IEEE 802.15.4 device not ready");
469 		return false;
470 	}
471 
472 	radio_api = (struct ieee802154_radio_api *)ieee802154_dev->api;
473 
474 	/**
475 	 * Do actual initialization of the chip
476 	 */
477 	get_mac(ieee802154_dev);
478 
479 	if (IEEE802154_HW_FILTER &
480 	    radio_api->get_capabilities(ieee802154_dev)) {
481 		struct ieee802154_filter filter;
482 		uint16_t short_addr;
483 
484 		/* Set short address */
485 		short_addr = (mac_addr[0] << 8) + mac_addr[1];
486 		filter.short_addr = short_addr;
487 
488 		radio_api->filter(ieee802154_dev, true,
489 				  IEEE802154_FILTER_TYPE_SHORT_ADDR,
490 				  &filter);
491 
492 		/* Set ieee address */
493 		filter.ieee_addr = mac_addr;
494 		radio_api->filter(ieee802154_dev, true,
495 				  IEEE802154_FILTER_TYPE_IEEE_ADDR,
496 				  &filter);
497 
498 #ifdef CONFIG_NET_CONFIG_SETTINGS
499 		LOG_INF("Set panid %x", CONFIG_NET_CONFIG_IEEE802154_PAN_ID);
500 
501 		filter.pan_id = CONFIG_NET_CONFIG_IEEE802154_PAN_ID;
502 
503 		radio_api->filter(ieee802154_dev, true,
504 				  IEEE802154_FILTER_TYPE_PAN_ID,
505 				  &filter);
506 #endif /* CONFIG_NET_CONFIG_SETTINGS */
507 	}
508 
509 #ifdef CONFIG_NET_CONFIG_SETTINGS
510 	LOG_INF("Set channel %u", CONFIG_NET_CONFIG_IEEE802154_CHANNEL);
511 	radio_api->set_channel(ieee802154_dev,
512 			       CONFIG_NET_CONFIG_IEEE802154_CHANNEL);
513 #endif /* CONFIG_NET_CONFIG_SETTINGS */
514 
515 	/* Start ieee802154 */
516 	radio_api->start(ieee802154_dev);
517 
518 	return true;
519 }
520 
net_recv_data(struct net_if * iface,struct net_pkt * pkt)521 int net_recv_data(struct net_if *iface, struct net_pkt *pkt)
522 {
523 	LOG_DBG("Received pkt %p, len %d", pkt, net_pkt_get_len(pkt));
524 
525 	k_fifo_put(&tx_queue, pkt);
526 
527 	return 0;
528 }
529 
ieee802154_handle_ack(struct net_if * iface,struct net_pkt * pkt)530 enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt)
531 {
532 	return NET_CONTINUE;
533 }
534 
main(void)535 int main(void)
536 {
537 	uint32_t baudrate, dtr = 0U;
538 	int ret;
539 
540 	LOG_INF("Starting wpan_serial application");
541 
542 	if (!device_is_ready(uart_dev)) {
543 		LOG_ERR("CDC ACM device not ready");
544 		return 0;
545 	}
546 
547 	ret = usb_enable(NULL);
548 	if (ret != 0) {
549 		LOG_ERR("Failed to enable USB");
550 		return 0;
551 	}
552 
553 	LOG_DBG("Wait for DTR");
554 
555 	while (1) {
556 		uart_line_ctrl_get(uart_dev, UART_LINE_CTRL_DTR, &dtr);
557 		if (dtr) {
558 			break;
559 		} else {
560 			/* Give CPU resources to low priority threads. */
561 			k_sleep(K_MSEC(100));
562 		}
563 	}
564 
565 	LOG_DBG("DTR set, continue");
566 
567 	ret = uart_line_ctrl_get(uart_dev, UART_LINE_CTRL_BAUD_RATE, &baudrate);
568 	if (ret) {
569 		LOG_WRN("Failed to get baudrate, ret code %d", ret);
570 	} else {
571 		LOG_DBG("Baudrate detected: %d", baudrate);
572 	}
573 
574 	LOG_INF("USB serial initialized");
575 
576 	/* Initialize net_pkt */
577 	net_pkt_init();
578 
579 	/* Initialize RX queue */
580 	init_rx_queue();
581 
582 	/* Initialize TX queue */
583 	init_tx_queue();
584 
585 	/* Initialize ieee802154 device */
586 	if (!init_ieee802154()) {
587 		LOG_ERR("Unable to initialize ieee802154");
588 		return 0;
589 	}
590 
591 	uart_irq_callback_set(uart_dev, interrupt_handler);
592 
593 	/* Enable rx interrupts */
594 	uart_irq_rx_enable(uart_dev);
595 	return 0;
596 }
597