| /* net_driver_15_4.c - IP 15.4 driver */ |
| |
| /* |
| * Copyright (c) 2015 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <nanokernel.h> |
| #include <toolchain.h> |
| #include <sections.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| #if defined(CONFIG_STDOUT_CONSOLE) |
| #include <stdio.h> |
| #define PRINT printf |
| #else |
| #include <misc/printk.h> |
| #define PRINT printk |
| #endif |
| |
| #include "contiki/ip/uip-debug.h" |
| |
| #include <net/net_core.h> |
| #include <net/l2_buf.h> |
| #include <net/net_ip.h> |
| #include <net/net_socket.h> |
| #include "contiki/netstack.h" |
| #include <net_driver_15_4.h> |
| |
| #if !defined(CONFIG_NETWORK_IP_STACK_DEBUG_15_4_NET_DRIVER) |
| #undef NET_DBG |
| #define NET_DBG(...) |
| #endif |
| |
| /* Stacks for the tx & rx fibers. |
| * FIXME: stack size needs fine-tuning |
| */ |
| #define STACKSIZE_UNIT 1024 |
| |
| #ifndef CONFIG_15_4_RX_STACK_SIZE |
| #define CONFIG_15_4_RX_STACK_SIZE (STACKSIZE_UNIT * 1) |
| #endif |
| #ifndef CONFIG_15_4_TX_STACK_SIZE |
| #define CONFIG_15_4_TX_STACK_SIZE (STACKSIZE_UNIT * 4) |
| #endif |
| static char __noinit __stack rx_fiber_stack[CONFIG_15_4_RX_STACK_SIZE]; |
| static char __noinit __stack tx_fiber_stack[CONFIG_15_4_TX_STACK_SIZE]; |
| |
| /* Queue for incoming packets from hw driver */ |
| static struct nano_fifo rx_queue; |
| /* Queue for outgoing packets to IP stack */ |
| static struct nano_fifo tx_queue; |
| |
| static int net_driver_15_4_open(void) |
| { |
| return 0; |
| } |
| |
| static int net_driver_15_4_send(struct net_buf *buf) |
| { |
| #if defined(CONFIG_NETWORK_IP_STACK_DEBUG_15_4_NET_DRIVER) |
| int orig_len = ip_buf_len(buf); |
| #endif |
| |
| if (!NETSTACK_COMPRESS.compress(buf)) { |
| NET_DBG("compression failed\n"); |
| ip_buf_unref(buf); |
| return -EINVAL; |
| } |
| |
| NET_DBG("sending %d bytes (original len %d)\n", ip_buf_len(buf), |
| orig_len); |
| |
| nano_fifo_put(&tx_queue, buf); |
| return 1; |
| } |
| |
| static void net_tx_15_4_fiber(void) |
| { |
| NET_DBG("Starting 15.4 TX fiber (stack %d bytes)\n", |
| sizeof(tx_fiber_stack)); |
| |
| while (1) { |
| struct net_buf *buf; |
| |
| /* Get next packet from application - wait if necessary */ |
| buf = nano_fifo_get(&tx_queue, TICKS_UNLIMITED); |
| |
| if (uip_len(buf) == 0) { |
| /* It is possible that uIP stack overwrote the len. |
| * We need to fix this here. |
| */ |
| uip_len(buf) = ip_buf_len(buf); |
| } |
| |
| NET_DBG("Sending (%u bytes) to 15.4 stack\n", |
| ip_buf_len(buf)); |
| |
| if (!NETSTACK_FRAGMENT.fragment(buf, NULL)) { |
| /* Release buffer on error */ |
| ip_buf_unref(buf); |
| } |
| |
| net_analyze_stack("802.15.4 TX", tx_fiber_stack, |
| sizeof(tx_fiber_stack)); |
| } |
| } |
| |
| static void net_rx_15_4_fiber(void) |
| { |
| struct net_buf *buf; |
| #if NET_MAC_CONF_STATS |
| int byte_count; |
| #endif |
| |
| NET_DBG("Starting 15.4 RX fiber (stack %d bytes)\n", |
| sizeof(rx_fiber_stack)); |
| |
| while (1) { |
| /* Wait next packet from 15.4 stack */ |
| buf = nano_fifo_get(&rx_queue, TICKS_UNLIMITED); |
| |
| #if NET_MAC_CONF_STATS |
| byte_count = uip_pkt_buflen(buf); |
| #endif |
| if (!NETSTACK_RDC.input(buf)) { |
| NET_DBG("802.15.4 RDC input failed, " |
| "buf %p discarded\n", buf); |
| l2_buf_unref(buf); |
| } else { |
| #if NET_MAC_CONF_STATS |
| net_mac_stats.bytes_received += byte_count; |
| #endif |
| } |
| |
| net_analyze_stack("802.15.4 RX", rx_fiber_stack, |
| sizeof(rx_fiber_stack)); |
| } |
| } |
| |
| static void init_rx_queue(void) |
| { |
| nano_fifo_init(&rx_queue); |
| |
| fiber_start(rx_fiber_stack, sizeof(rx_fiber_stack), |
| (nano_fiber_entry_t) net_rx_15_4_fiber, 0, 0, 7, 0); |
| } |
| |
| static void init_tx_queue(void) |
| { |
| nano_fifo_init(&tx_queue); |
| |
| fiber_start(tx_fiber_stack, sizeof(tx_fiber_stack), |
| (nano_fiber_entry_t) net_tx_15_4_fiber, 0, 0, 7, 0); |
| } |
| |
| static struct net_driver net_driver_15_4 = { |
| .head_reserve = 0, |
| .open = net_driver_15_4_open, |
| .send = net_driver_15_4_send, |
| }; |
| |
| int net_driver_15_4_init(void) |
| { |
| init_tx_queue(); |
| init_rx_queue(); |
| |
| NETSTACK_RADIO.init(); |
| NETSTACK_RDC.init(); |
| NETSTACK_MAC.init(); |
| NETSTACK_COMPRESS.init(); |
| |
| net_register_driver(&net_driver_15_4); |
| |
| return 0; |
| } |
| |
| int net_driver_15_4_recv(struct net_buf *buf) |
| { |
| if (!NETSTACK_COMPRESS.uncompress(buf)) { |
| return -EINVAL; |
| } |
| |
| if (net_recv(buf) < 0) { |
| NET_DBG("input to IP stack failed\n"); |
| return -EINVAL; |
| } |
| |
| return 0; |
| } |
| |
| int net_driver_15_4_recv_from_hw(struct net_buf *buf) |
| { |
| nano_fifo_put(&rx_queue, buf); |
| return 0; |
| } |