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