diff --git a/Kconfig b/Kconfig index e61975bd33e..a44ef1f3c7d 100644 --- a/Kconfig +++ b/Kconfig @@ -1799,6 +1799,11 @@ source libs/libxx/Kconfig source libs/libdsp/Kconfig endmenu +menu "Open Asymmetric Multi Processing" +source openamp/Kconfig +endmenu + menu "Application Configuration" source "$APPSDIR/Kconfig" endmenu + diff --git a/drivers/Kconfig b/drivers/Kconfig index 06aff05727e..8341c7efa53 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -312,6 +312,17 @@ endif # PIPES source drivers/power/Kconfig +menuconfig RPTUN + bool "Remote Proc Tunnel Driver Support" + default n + depends on OPENAMP + ---help--- + RPTUN driver is used for multi-cores' communication. + +if RPTUN +source drivers/rptun/Kconfig +endif # RPTUN + menuconfig SENSORS bool "Sensor Device Support" default n diff --git a/drivers/Makefile b/drivers/Makefile index c5c40db07b1..a79545480c4 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -68,6 +68,7 @@ include eeprom$(DELIM)Make.defs include net$(DELIM)Make.defs include pipes$(DELIM)Make.defs include power$(DELIM)Make.defs +include rptun$(DELIM)Make.defs include sensors$(DELIM)Make.defs include serial$(DELIM)Make.defs include spi$(DELIM)Make.defs diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f8f60ab5d55..df323c25a9d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -16,6 +16,29 @@ config NETDEV_LOOPBACK if NETDEV_LOOPBACK endif # NETDEV_LOOPBACK +config NET_RPMSG_DRV + bool "RPMSG net driver" + depends on NET && OPENAMP + select ARCH_HAVE_NETDEV_STATISTICS + ---help--- + Use the rpmsg as net device, transfer packet between remoteproc. + +if NET_RPMSG_DRV + +config NET_RPMSG_PRIORITY + int "net prmsg priority" + default 100 + ---help--- + The priority for net rmpsg task. + +config NET_RPMSG_STACKSIZE + int "net rpmsg stack size" + default 2048 + ---help--- + The stack size allocated for the net rpmsg task. + +endif # NET_RPMSG_DRV + config NETDEV_TELNET bool "Telnet driver" default n diff --git a/drivers/net/Make.defs b/drivers/net/Make.defs index 3cea3c8f4c5..54e5ba81f9c 100644 --- a/drivers/net/Make.defs +++ b/drivers/net/Make.defs @@ -43,6 +43,10 @@ ifeq ($(CONFIG_NETDEV_LOOPBACK),y) CSRCS += loopback.c endif +ifeq ($(CONFIG_NET_RPMSG_DRV),y) + CSRCS += rpmsgdrv.c +endif + ifeq ($(CONFIG_NETDEV_TELNET),y) CSRCS += telnet.c endif diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c new file mode 100644 index 00000000000..4346b1c47f3 --- /dev/null +++ b/drivers/net/rpmsgdrv.c @@ -0,0 +1,1418 @@ +/**************************************************************************** + * drivers/net/rpmsgdrv.c + * + * Copyright (C) 2018 Pinecone Inc. All rights reserved. + * Author: Jianli Dong + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The address family that we used to create the socket really does not + * matter. It should, however, be valid in the current configuration. + */ + +#if defined(CONFIG_NET_IPv4) +# define NET_RPMSG_DRV_FAMILY AF_INET +#elif defined(CONFIG_NET_IPv6) +# define NET_RPMSG_DRV_FAMILY AF_INET6 +#elif defined(CONFIG_NET_IEEE802154) +# define NET_RPMSG_DRV_FAMILY AF_IEEE802154 +#elif defined(CONFIG_WIRELESS_PKTRADIO) +# define NET_RPMSG_DRV_FAMILY AF_PKTRADIO +#elif defined(CONFIG_NET_USRSOCK) +# define NET_RPMSG_DRV_FAMILY AF_INET +#elif defined(CONFIG_NET_PKT) +# define NET_RPMSG_DRV_FAMILY AF_PACKET +#elif defined(CONFIG_NET_LOCAL) +# define NET_RPMSG_DRV_FAMILY AF_LOCAL +#else +# define NET_RPMSG_DRV_FAMILY AF_UNSPEC +#endif + +/* SOCK_DGRAM is the preferred socket type to use when we just want a + * socket for performing driver ioctls. However, we can't use SOCK_DRAM + * if UDP is disabled. + * + * Pick a socket type (and perhaps protocol) compatible with the currently + * selected address family. + */ + +#if NET_RPMSG_DRV_FAMILY == AF_INET +# if defined(CONFIG_NET_UDP) +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +# elif defined(CONFIG_NET_TCP) +# define NET_RPMSG_DRV_TYPE SOCK_STREAM +# elif defined(CONFIG_NET_ICMP_SOCKET) +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +# define NET_RPMSG_DRV_PROTOCOL IPPROTO_ICMP +# endif +#elif NET_RPMSG_DRV_FAMILY == AF_INET6 +# if defined(CONFIG_NET_UDP) +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +# elif defined(CONFIG_NET_TCP) +# define NET_RPMSG_DRV_TYPE SOCK_STREAM +# elif defined(CONFIG_NET_ICMPv6_SOCKET) +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +# define NET_RPMSG_DRV_PROTOCOL IPPROTO_ICMP6 +# endif +#elif NET_RPMSG_DRV_FAMILY == AF_IEEE802154 +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +#elif NET_RPMSG_DRV_FAMILY == AF_PKTRADIO +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +#elif NET_RPMSG_DRV_FAMILY == AF_PACKET +# define NET_RPMSG_DRV_TYPE SOCK_RAW +#elif NET_RPMSG_DRV_FAMILY == AF_LOCAL +# if defined(CONFIG_NET_LOCAL_DGRAM) +# define NET_RPMSG_DRV_TYPE SOCK_DGRAM +# elif defined(CONFIG_NET_LOCAL_STREAM) +# define NET_RPMSG_DRV_TYPE SOCK_STREAM +# endif +#endif + +/* Socket protocol of zero normally works */ + +#ifndef NET_RPMSG_DRV_PROTOCOL +# define NET_RPMSG_DRV_PROTOCOL 0 +#endif + +/* Work queue support is required. */ + +#if !defined(CONFIG_SCHED_WORKQUEUE) +# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE) +#endif + +#ifdef CONFIG_NET_DUMPPACKET +# define net_rpmsg_drv_dumppacket lib_dumpbuffer +#else +# define net_rpmsg_drv_dumppacket(m, b, l) +#endif + +/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per second */ + +#define NET_RPMSG_DRV_WDDELAY (1*CLK_TCK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct net_rpmsg_drv_cookie_s +{ + FAR struct net_rpmsg_header_s *header; + sem_t sem; +}; + +/* net_rpmsg_drv_s encapsulates all state information for a single hardware + * interface + */ + +struct net_rpmsg_drv_s +{ + FAR const char *cpuname; + FAR const char *devname; + struct rpmsg_endpoint ept; + WDOG_ID txpoll; /* TX poll timer */ + struct work_s pollwork; /* For deferring poll work to the work queue */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; /* Interface understood by the network */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Common TX logic */ + +static int net_rpmsg_drv_transmit(FAR struct net_driver_s *dev, + bool nocopy); +static int net_rpmsg_drv_txpoll(FAR struct net_driver_s *dev); +static void net_rpmsg_drv_reply(FAR struct net_driver_s *dev); + +/* RPMSG related functions */ + +static int net_rpmsg_drv_default_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int net_rpmsg_drv_sockioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int net_rpmsg_drv_transfer_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static void net_rpmsg_drv_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_); +static void net_rpmsg_drv_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_); +static int net_rpmsg_drv_ept_cb(FAR struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, FAR void *priv); + +static int net_rpmsg_drv_send_recv(struct net_driver_s *dev, + void *header_, uint32_t command, int len); + +/* Watchdog timer expirations */ + +static void net_rpmsg_drv_poll_work(FAR void *arg); +static void net_rpmsg_drv_poll_expiry(int argc, wdparm_t arg, ...); + +/* NuttX callback functions */ + +static int net_rpmsg_drv_ifup(FAR struct net_driver_s *dev); +static int net_rpmsg_drv_ifdown(FAR struct net_driver_s *dev); + +static void net_rpmsg_drv_txavail_work(FAR void *arg); +static int net_rpmsg_drv_txavail(FAR struct net_driver_s *dev); + +#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6) +static int net_rpmsg_drv_addmac(FAR struct net_driver_s *dev, + FAR const uint8_t *mac); +#ifdef CONFIG_NET_IGMP +static int net_rpmsg_drv_rmmac(FAR struct net_driver_s *dev, + FAR const uint8_t *mac); +#endif +#ifdef CONFIG_NET_ICMPv6 +static void net_rpmsg_drv_ipv6multicast(FAR struct net_driver_s *dev); +#endif +#endif +#ifdef CONFIG_NETDEV_IOCTL +static int net_rpmsg_drv_ioctl(FAR struct net_driver_s *dev, int cmd, + unsigned long arg); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const rpmsg_ept_cb g_net_rpmsg_drv_handler[] = +{ + [NET_RPMSG_IFUP] = net_rpmsg_drv_default_handler, + [NET_RPMSG_IFDOWN] = net_rpmsg_drv_default_handler, + [NET_RPMSG_ADDMCAST] = net_rpmsg_drv_default_handler, + [NET_RPMSG_RMMCAST] = net_rpmsg_drv_default_handler, + [NET_RPMSG_DEVIOCTL] = net_rpmsg_drv_default_handler, + [NET_RPMSG_SOCKIOCTL] = net_rpmsg_drv_sockioctl_handler, + [NET_RPMSG_TRANSFER] = net_rpmsg_drv_transfer_handler, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void net_rpmsg_drv_wait(FAR sem_t *sem) +{ + int ret; + + do + { + /* Take the semaphore (perhaps waiting) */ + + ret = net_lockedwait(sem); + + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + DEBUGASSERT(ret == OK || ret == -EINTR); + } + while (ret == -EINTR); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_transmit + * + * Description: + * Start hardware transmission. Called from watchdog based polling. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static int net_rpmsg_drv_transmit(FAR struct net_driver_s *dev, bool nocopy) +{ + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + FAR struct net_rpmsg_transfer_s *msg; + int ret; + + /* Verify that the hardware is ready to send another packet. If we get + * here, then we are committed to sending a packet; Higher level logic + * must have assured that there is no transmission in progress. + */ + + /* Increment statistics */ + + net_rpmsg_drv_dumppacket("transmit", dev->d_buf, dev->d_len); + NETDEV_TXPACKETS(dev); + + /* Send the packet: address=dev->d_buf, length=dev->d_len */ + + msg = (FAR struct net_rpmsg_transfer_s *)dev->d_buf - 1; + + msg->header.command = NET_RPMSG_TRANSFER; + msg->header.result = 0; + msg->header.cookie = 0; + msg->length = dev->d_len; + + if (nocopy) + { + ret = rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) + msg->length); + } + else + { + ret = rpmsg_send(&priv->ept, msg, sizeof(*msg) + msg->length); + } + + if (ret < 0) + { + NETDEV_TXERRORS(dev); + return ret; + } + else + { + NETDEV_TXDONE(dev); + return OK; + } +} + +/**************************************************************************** + * Name: net_rpmsg_drv_txpoll + * + * Description: + * The transmitter is available, check if the network has any outgoing + * packets ready to send. This is a callback from devif_poll(). + * devif_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. When the preceding TX packet send fail + * 3. During normal TX polling + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * OK on success; a negated errno on failure + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static int net_rpmsg_drv_txpoll(FAR struct net_driver_s *dev) +{ + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + uint32_t size; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (dev->d_len > 0) + { + /* Look up the destination MAC address and add it to the Ethernet + * header. + */ + +#ifdef CONFIG_NET_IPv4 + if (IFF_IS_IPv4(dev->d_flags)) + { + arp_out(dev); + } +#endif /* CONFIG_NET_IPv4 */ + +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv6(dev->d_flags)) + { + neighbor_out(dev); + } +#endif /* CONFIG_NET_IPv6 */ + + if (!devif_loopback(dev)) + { + /* Send the packet */ + + net_rpmsg_drv_transmit(dev, true); + + /* Check if there is room in the device to hold another packet. If not, + * return a non-zero value to terminate the poll. + */ + + dev->d_buf = rpmsg_get_tx_payload_buffer(&priv->ept, &size, false); + if (dev->d_buf) + { + dev->d_buf += sizeof(struct net_rpmsg_transfer_s); + dev->d_pktsize = size - sizeof(struct net_rpmsg_transfer_s); + } + + return dev->d_buf == NULL; + } + } + + /* If zero is returned, the polling will continue until all connections have + * been examined. + */ + + return 0; +} + +/**************************************************************************** + * Name: net_rpmsg_drv_reply + * + * Description: + * After a packet has been received and dispatched to the network, it + * may return with an outgoing packet. This function checks for + * that case and performs the transmission if necessary. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static void net_rpmsg_drv_reply(FAR struct net_driver_s *dev) +{ + /* If the packet dispatch resulted in data that should be sent out on the + * network, the field d_len will set to a value > 0. + */ + + if (dev->d_len > 0) + { + /* Update the Ethernet header with the correct MAC address */ + +#ifdef CONFIG_NET_IPv4 + if (IFF_IS_IPv4(dev->d_flags)) + { + arp_out(dev); + } +#endif + +#ifdef CONFIG_NET_IPv6 + if (IFF_IS_IPv6(dev->d_flags)) + { + neighbor_out(dev); + } +#endif + + /* And send the packet */ + + net_rpmsg_drv_transmit(dev, false); + } +} + +/* RPMSG related functions */ + +static int net_rpmsg_drv_default_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct net_rpmsg_header_s *header = data; + FAR struct net_rpmsg_drv_cookie_s *cookie = + (struct net_rpmsg_drv_cookie_s *)(uintptr_t)header->cookie; + + memcpy(cookie->header, header, len); + nxsem_post(&cookie->sem); + return 0; +} + +static int net_rpmsg_drv_sockioctl_task(int argc, FAR char *argv[]) +{ + FAR struct net_rpmsg_ioctl_s *msg; + FAR struct rpmsg_endpoint *ept; + struct socket sock; + + int domain = NET_RPMSG_DRV_FAMILY; + int type = NET_RPMSG_DRV_TYPE; + int protocol = NET_RPMSG_DRV_PROTOCOL; + + /* Restore pointers from argv */ + + ept = (FAR struct rpmsg_endpoint *)strtoul(argv[1], NULL, 0); + msg = (FAR struct net_rpmsg_ioctl_s *)strtoul(argv[2], NULL, 0); + + /* We need a temporary sock for ioctl here */ + + if (msg->code == SIOCIFAUTOCONF) + { + domain = PF_INET6; + type = SOCK_DGRAM; + protocol = IPPROTO_ICMP6; + } + + sock.s_crefs = 1; /* Initialize reference count manually */ + msg->header.result = psock_socket(domain, type, protocol, &sock); + if (msg->header.result >= 0) + { + msg->header.result = psock_ioctl(&sock, msg->code, (unsigned long)msg->arg); + psock_close(&sock); /* Close the temporary sock */ + } + + /* Send the response only when cookie doesn't equal NULL */ + + if (msg->header.cookie) + { + rpmsg_send(ept, msg, sizeof(*msg) + msg->length); + } + + rpmsg_release_rx_buffer(ept, msg); + return 0; +} + +static int net_rpmsg_drv_sockioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR char *argv[3]; + char arg1[16]; + char arg2[16]; + + /* Save pointers into argv */ + + sprintf(arg1, "%#p", ept); + sprintf(arg2, "%#p", data); + + argv[0] = arg1; + argv[1] = arg2; + argv[2] = NULL; + + /* Move the action into a temp thread to avoid the deadlock */ + + rpmsg_hold_rx_buffer(ept, data); + kthread_create("rpmsg-net", CONFIG_NET_RPMSG_PRIORITY, + CONFIG_NET_RPMSG_STACKSIZE, net_rpmsg_drv_sockioctl_task, argv); + + return 0; +} + +#ifdef CONFIG_NET_IPv4 +static bool net_rpmsg_drv_is_ipv4(FAR struct net_driver_s *dev) +{ + FAR struct ipv4_hdr_s *ip = (struct ipv4_hdr_s *)(dev->d_buf + dev->d_llhdrlen); + FAR struct eth_hdr_s *eth = (struct eth_hdr_s *)dev->d_buf; + + if (dev->d_lltype == NET_LL_ETHERNET || dev->d_lltype == NET_LL_IEEE80211) + { + return eth->type == HTONS(ETHTYPE_IP); + } + else + { + return (ip->vhl & IP_VERSION_MASK) == IPv4_VERSION; + } +} +#endif + +#ifdef CONFIG_NET_IPv6 +static bool net_rpmsg_drv_is_ipv6(FAR struct net_driver_s *dev) +{ + FAR struct ipv6_hdr_s *ip = (struct ipv6_hdr_s *)(dev->d_buf + dev->d_llhdrlen); + FAR struct eth_hdr_s *eth = (struct eth_hdr_s *)dev->d_buf; + + if (dev->d_lltype == NET_LL_ETHERNET || dev->d_lltype == NET_LL_IEEE80211) + { + return eth->type == HTONS(ETHTYPE_IP6); + } + else + { + return (ip->vtc & IP_VERSION_MASK) == IPv6_VERSION; + } +} +#endif + +#ifdef CONFIG_NET_ARP +static bool net_rpmsg_drv_is_arp(FAR struct net_driver_s *dev) +{ + FAR struct eth_hdr_s *eth = (struct eth_hdr_s *)dev->d_buf; + + if (dev->d_lltype == NET_LL_ETHERNET || dev->d_lltype == NET_LL_IEEE80211) + { + return eth->type == HTONS(ETHTYPE_ARP); + } + else + { + return false; + } +} +#endif + +/**************************************************************************** + * Name: net_rpmsg_drv_transfer_handler + * + * Description: + * An message was received indicating the availability of a new RX packet + * + * Parameters: + * ept - Reference to the endpoint which receive the message + * + * Returned Value: + * OK on success + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static int net_rpmsg_drv_transfer_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct net_driver_s *dev = ept->priv; + FAR struct net_rpmsg_transfer_s *msg = data; + FAR void *oldbuf; + + /* Lock the network and serialize driver operations if necessary. + * NOTE: Serialization is only required in the case where the driver work + * is performed on an LP worker thread and where more than one LP worker + * thread has been configured. + */ + + net_lock(); + + /* Check for errors and update statistics */ + + net_rpmsg_drv_dumppacket("receive", msg->data, msg->length); + + NETDEV_RXPACKETS(dev); + + /* Copy the data from the hardware to dev->d_buf. Set + * amount of data in dev->d_len + */ + + oldbuf = dev->d_buf; + + dev->d_buf = msg->data; + dev->d_len = msg->length; + +#ifdef CONFIG_NET_PKT + /* When packet sockets are enabled, feed the frame into the packet tap */ + + pkt_input(dev); +#endif + + /* We only accept IP packets of the configured type and ARP packets */ + +#ifdef CONFIG_NET_IPv4 + if (net_rpmsg_drv_is_ipv4(dev)) + { + ninfo("IPv4 frame\n"); + NETDEV_RXIPV4(dev); + + /* Handle ARP on input, then dispatch IPv4 packet to the network + * layer. + */ + + arp_ipin(dev); + ipv4_input(dev); + + /* Check for a reply to the IPv4 packet */ + + net_rpmsg_drv_reply(dev); + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (net_rpmsg_drv_is_ipv6(dev)) + { + ninfo("Iv6 frame\n"); + NETDEV_RXIPV6(dev); + + /* Dispatch IPv6 packet to the network layer */ + + ipv6_input(dev); + + /* Check for a reply to the IPv6 packet */ + + net_rpmsg_drv_reply(dev); + } + else +#endif +#ifdef CONFIG_NET_ARP + if (net_rpmsg_drv_is_arp(dev)) + { + ninfo("ARP frame\n"); + NETDEV_RXARP(dev); + + /* Dispatch ARP packet to the network layer */ + + arp_arpin(dev); + + /* Check for a reply to the ARP packet */ + + net_rpmsg_drv_reply(dev); + } + else +#endif + { + NETDEV_RXDROPPED(dev); + } + + dev->d_buf = oldbuf; + net_unlock(); + + return 0; +} + +static void net_rpmsg_drv_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct net_driver_s *dev = priv_; + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + char eptname[RPMSG_NAME_SIZE]; + + if (!strcmp(priv->cpuname, rpmsg_get_cpuname(rdev))) + { + priv->ept.priv = dev; + sprintf(eptname, NET_RPMSG_EPT_NAME, priv->devname); + + rpmsg_create_ept(&priv->ept, rdev, eptname, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + net_rpmsg_drv_ept_cb, NULL); + } +} + +static void net_rpmsg_drv_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct net_driver_s *dev = priv_; + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + + if (!strcmp(priv->cpuname, rpmsg_get_cpuname(rdev))) + { + rpmsg_destroy_ept(&priv->ept); + dev->d_buf = NULL; + } +} + +static int net_rpmsg_drv_ept_cb(FAR struct rpmsg_endpoint *ept, void *data, + size_t len, uint32_t src, FAR void *priv) +{ + FAR struct net_rpmsg_header_s *header = data; + uint32_t command = header->command; + + if (command < sizeof(g_net_rpmsg_drv_handler) / sizeof(g_net_rpmsg_drv_handler[0])) + { + return g_net_rpmsg_drv_handler[command](ept, data, len, src, priv); + } + + return -EINVAL; +} + +static int net_rpmsg_drv_send_recv(FAR struct net_driver_s *dev, + FAR void *header_, uint32_t command, + int len) +{ + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + FAR struct net_rpmsg_header_s *header = header_; + FAR struct net_rpmsg_drv_cookie_s cookie; + int ret; + + nxsem_init(&cookie.sem, 0, 0); + nxsem_setprotocol(&cookie.sem, SEM_PRIO_NONE); + + cookie.header = header; + header->command = command; + header->result = -ENXIO; + header->cookie = (uintptr_t)&cookie; + + ret = rpmsg_send(&priv->ept, header, len); + if (ret < 0) + { + goto out; + } + + net_rpmsg_drv_wait(&cookie.sem); + ret = cookie.header->result; + +out: + nxsem_destroy(&cookie.sem); + return ret; +} + +/**************************************************************************** + * Name: net_rpmsg_drv_poll_work + * + * Description: + * Perform periodic polling from the worker thread + * + * Parameters: + * arg - The argument passed when work_queue() as called. + * + * Returned Value: + * OK on success + * + * Assumptions: + * Run on a work queue thread. + * + ****************************************************************************/ + +static void net_rpmsg_drv_poll_work(FAR void *arg) +{ + FAR struct net_driver_s *dev = arg; + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + uint32_t size; + + /* Lock the network and serialize driver operations if necessary. + * NOTE: Serialization is only required in the case where the driver work + * is performed on an LP worker thread and where more than one LP worker + * thread has been configured. + */ + + net_lock(); + + /* Perform the poll */ + + /* Check if there is room in the send another TX packet. We cannot perform + * the TX poll if he are unable to accept another packet for transmission. + */ + + if (dev->d_buf == NULL) + { + /* Try to get the payload buffer if not yet */ + + dev->d_buf = rpmsg_get_tx_payload_buffer(&priv->ept, &size, false); + if (dev->d_buf) + { + dev->d_buf += sizeof(struct net_rpmsg_transfer_s); + dev->d_pktsize = size - sizeof(struct net_rpmsg_transfer_s); + } + } + + if (dev->d_buf) + { + /* If so, update TCP timing states and poll the network for new XMIT data. + * Hmmm.. might be bug here. Does this mean if there is a transmit in + * progress, we will missing TCP time state updates? + */ + + devif_timer(dev, net_rpmsg_drv_txpoll); + } + + /* Setup the watchdog poll timer again */ + + wd_start(priv->txpoll, NET_RPMSG_DRV_WDDELAY, net_rpmsg_drv_poll_expiry, 1, + (wdparm_t)dev); + net_unlock(); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_poll_expiry + * + * Description: + * Periodic timer handler. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Runs in the context of a the timer interrupt handler. Local + * interrupts are disabled by the interrupt logic. + * + ****************************************************************************/ + +static void net_rpmsg_drv_poll_expiry(int argc, wdparm_t arg, ...) +{ + FAR struct net_driver_s *dev = (FAR struct net_driver_s *)arg; + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + + /* Schedule to perform the interrupt processing on the worker thread. */ + + work_queue(LPWORK, &priv->pollwork, net_rpmsg_drv_poll_work, dev, 0); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_ifup + * + * Description: + * NuttX Callback: Bring up the link interface when an IP address is + * provided + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static int net_rpmsg_drv_ifup(FAR struct net_driver_s *dev) +{ + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + struct net_rpmsg_ifup_s msg = + { + }; + + int ret; + +#ifdef CONFIG_NET_IPv4 + ninfo("Bringing up: %d.%d.%d.%d\n", + dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, + (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); +#endif +#ifdef CONFIG_NET_IPv6 + ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); +#endif + + net_lock(); + + /* Prepare the message */ + + msg.lnkaddr.length = netdev_lladdrsize(dev); + memcpy(msg.lnkaddr.addr, &dev->d_mac, msg.lnkaddr.length); + +#ifdef CONFIG_NET_IPv4 + net_ipv4addr_copy(msg.ipaddr, dev->d_ipaddr); + net_ipv4addr_copy(msg.draddr, dev->d_draddr); + net_ipv4addr_copy(msg.netmask, dev->d_netmask); +#endif + +#ifdef CONFIG_NET_IPv6 + net_ipv6addr_copy(msg.ipv6addr, dev->d_ipv6addr); + net_ipv6addr_copy(msg.ipv6draddr, dev->d_ipv6draddr); + net_ipv6addr_copy(msg.ipv6netmask, dev->d_ipv6netmask); +#endif + + /* Send the message */ + + ret = net_rpmsg_drv_send_recv(dev, &msg, NET_RPMSG_IFUP, sizeof(msg)); + if (ret < 0) + { + net_unlock(); + return ret; + } + + /* Update net_driver_t field */ + + memcpy(&dev->d_mac, msg.lnkaddr.addr, msg.lnkaddr.length); + +#ifdef CONFIG_NET_IPv4 + net_ipv4addr_copy(dev->d_ipaddr, msg.ipaddr); + net_ipv4addr_copy(dev->d_draddr, msg.draddr); + net_ipv4addr_copy(dev->d_netmask, msg.netmask); +#endif + +#ifdef CONFIG_NET_IPv6 + net_ipv6addr_copy(dev->d_ipv6addr, msg.ipv6addr); + net_ipv6addr_copy(dev->d_ipv6draddr, msg.ipv6draddr); + net_ipv6addr_copy(dev->d_ipv6netmask, msg.ipv6netmask); +#endif + +#ifdef CONFIG_NET_ICMPv6 + /* Set up IPv6 multicast address filtering */ + + net_rpmsg_drv_ipv6multicast(dev); +#endif + + /* Set and activate a timer process */ + + wd_start(priv->txpoll, NET_RPMSG_DRV_WDDELAY, net_rpmsg_drv_poll_expiry, 1, + (wdparm_t)dev); + + net_unlock(); + +#ifdef CONFIG_NETDB_DNSCLIENT +# ifdef CONFIG_NET_IPv4 + if (!net_ipv4addr_cmp(msg.dnsaddr, INADDR_ANY)) + { + struct sockaddr_in dnsaddr = + { + }; + + dnsaddr.sin_family = AF_INET; + dnsaddr.sin_port = htons(DNS_DEFAULT_PORT); + memcpy(&dnsaddr.sin_addr, &msg.dnsaddr, sizeof(msg.dnsaddr)); + + dns_add_nameserver((FAR const struct sockaddr *)&dnsaddr, sizeof(dnsaddr)); + } +# endif + +# ifdef CONFIG_NET_IPv6 + if (!net_ipv6addr_cmp(msg.ipv6dnsaddr, &in6addr_any)) + { + struct sockaddr_in6 dnsaddr = + { + }; + + dnsaddr.sin6_family = AF_INET6; + dnsaddr.sin6_port = htons(DNS_DEFAULT_PORT); + memcpy(&dnsaddr.sin6_addr, msg.ipv6dnsaddr, sizeof(msg.ipv6dnsaddr)); + + dns_add_nameserver((FAR const struct sockaddr *)&dnsaddr, sizeof(dnsaddr)); + } +# endif +#endif + + return OK; +} + +/**************************************************************************** + * Name: net_rpmsg_drv_ifdown + * + * Description: + * NuttX Callback: Stop the interface. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static int net_rpmsg_drv_ifdown(FAR struct net_driver_s *dev) +{ + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + FAR struct net_rpmsg_ifdown_s msg; + irqstate_t flags; + + /* Disable the interrupt */ + + flags = enter_critical_section(); + + /* Cancel the TX poll timer and work */ + + wd_cancel(priv->txpoll); + work_cancel(LPWORK, &priv->pollwork); + + leave_critical_section(flags); + + /* Put the EMAC in its reset, non-operational state. This should be + * a known configuration that will guarantee the net_rpmsg_drv_ifup() always + * successfully brings the interface back up. + */ + + return net_rpmsg_drv_send_recv(dev, &msg, NET_RPMSG_IFDOWN, sizeof(msg)); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Runs on a work queue thread. + * + ****************************************************************************/ + +static void net_rpmsg_drv_txavail_work(FAR void *arg) +{ + FAR struct net_driver_s *dev = arg; + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + uint32_t size; + + /* Lock the network and serialize driver operations if necessary. + * NOTE: Serialization is only required in the case where the driver work + * is performed on an LP worker thread and where more than one LP worker + * thread has been configured. + */ + + net_lock(); + + /* Ignore the notification if the interface is not yet up */ + + if (IFF_IS_UP(dev->d_flags)) + { + /* Try to get the payload buffer if not yet */ + + if (dev->d_buf == NULL) + { + dev->d_buf = rpmsg_get_tx_payload_buffer(&priv->ept, &size, false); + if (dev->d_buf) + { + dev->d_buf += sizeof(struct net_rpmsg_transfer_s); + dev->d_pktsize = size - sizeof(struct net_rpmsg_transfer_s); + } + } + + /* Check if there is room in the hardware to hold another outgoing packet. */ + + if (dev->d_buf) + { + /* If so, then poll the network for new XMIT data */ + + devif_poll(dev, net_rpmsg_drv_txpoll); + } + } + + net_unlock(); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static int net_rpmsg_drv_txavail(FAR struct net_driver_s *dev) +{ + FAR struct net_rpmsg_drv_s *priv = dev->d_private; + + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&priv->pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(LPWORK, &priv->pollwork, net_rpmsg_drv_txavail_work, dev, 0); + } + + return OK; +} + +/**************************************************************************** + * Name: net_rpmsg_drv_addmac + * + * Description: + * NuttX Callback: Add the specified MAC address to the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be added + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6) +static int net_rpmsg_drv_addmac(FAR struct net_driver_s *dev, + FAR const uint8_t *mac) +{ + struct net_rpmsg_mcast_s msg; + + /* Add the MAC address to the hardware multicast routing table */ + + msg.lnkaddr.length = netdev_lladdrsize(dev); + memcpy(msg.lnkaddr.addr, mac, msg.lnkaddr.length); + return net_rpmsg_drv_send_recv(dev, &msg, NET_RPMSG_ADDMCAST, sizeof(msg)); +} +#endif + +/**************************************************************************** + * Name: net_rpmsg_drv_rmmac + * + * Description: + * NuttX Callback: Remove the specified MAC address from the hardware multicast + * address filtering + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * mac - The MAC address to be removed + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IGMP +static int net_rpmsg_drv_rmmac(FAR struct net_driver_s *dev, + FAR const uint8_t *mac) +{ + struct net_rpmsg_mcast_s msg; + + /* Remove the MAC address from the hardware multicast routing table */ + + msg.lnkaddr.length = netdev_lladdrsize(dev); + memcpy(msg.lnkaddr.addr, mac, msg.lnkaddr.length); + return net_rpmsg_drv_send_recv(dev, &msg, NET_RPMSG_RMMCAST, sizeof(msg)); +} +#endif + +/**************************************************************************** + * Name: net_rpmsg_drv_ipv6multicast + * + * Description: + * Configure the IPv6 multicast MAC address. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ICMPv6 +static void net_rpmsg_drv_ipv6multicast(FAR struct net_driver_s *dev) +{ + if (dev->d_lltype == NET_LL_ETHERNET || dev->d_lltype == NET_LL_IEEE80211) + { + uint16_t tmp16; + uint8_t mac[6]; + + /* For ICMPv6, we need to add the IPv6 multicast address + * + * For IPv6 multicast addresses, the Ethernet MAC is derived by + * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00, + * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map + * to the Ethernet MAC address 33:33:00:01:00:03. + * + * NOTES: This appears correct for the ICMPv6 Router Solicitation + * Message, but the ICMPv6 Neighbor Solicitation message seems to + * use 33:33:ff:01:00:03. + */ + + mac[0] = 0x33; + mac[1] = 0x33; + + tmp16 = dev->d_ipv6addr[6]; + mac[2] = 0xff; + mac[3] = tmp16 >> 8; + + tmp16 = dev->d_ipv6addr[7]; + mac[4] = tmp16 & 0xff; + mac[5] = tmp16 >> 8; + + ninfo("IPv6 Multicast: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + net_rpmsg_drv_addmac(dev, mac); + +#if defined(CONFIG_NET_ETHERNET) && defined(CONFIG_NET_ICMPv6_AUTOCONF) + /* Add the IPv6 all link-local nodes Ethernet address. This is the + * address that we expect to receive ICMPv6 Router Advertisement + * packets. + */ + + net_rpmsg_drv_addmac(dev, g_ipv6_ethallnodes.ether_addr_octet); +#endif /* CONFIG_NET_ETHERNET && CONFIG_NET_ICMPv6_AUTOCONF */ + +#if defined(CONFIG_NET_ETHERNET) && defined(CONFIG_NET_ICMPv6_ROUTER) + /* Add the IPv6 all link-local routers Ethernet address. This is the + * address that we expect to receive ICMPv6 Router Solicitation + * packets. + */ + + net_rpmsg_drv_addmac(dev, g_ipv6_ethallrouters.ether_addr_octet); +#endif /* CONFIG_NET_ETHERNET && CONFIG_NET_ICMPv6_ROUTER */ + } +} +#endif /* CONFIG_NET_ICMPv6 */ + +/**************************************************************************** + * Name: net_rpmsg_drv_ioctl + * + * Description: + * Handle network IOCTL commands directed to this device. + * + * Parameters: + * dev - Reference to the NuttX driver state structure + * cmd - The IOCTL command + * arg - The argument for the IOCTL command + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int net_rpmsg_drv_ioctl(FAR struct net_driver_s *dev, int cmd, + unsigned long arg) +{ + ssize_t len; + int ret; + + len = net_ioctl_arglen(cmd); + if (len >= 0) + { + FAR struct net_rpmsg_ioctl_s *msg; + char buf[sizeof(*msg) + len]; + + msg = (FAR struct net_rpmsg_ioctl_s *)buf; + + msg->code = cmd; + msg->length = len; + memcpy(msg->arg, (FAR void *)arg, len); + + ret = net_rpmsg_drv_send_recv(dev, msg, + NET_RPMSG_DEVIOCTL, sizeof(*msg) + len); + if (ret >= 0) + { + memcpy((FAR void *)arg, msg->arg, len); + } + } + else + { + ret = len; + } + + return ret; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: net_rpmsg_drv_init + * + * Description: + * Initialize the net rpmsg driver + * + * Parameters: + * name - Specify the netdev name + * lltype - Identify the link type + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * Called early in initialization before multi-tasking is initiated. + * + ****************************************************************************/ + +int net_rpmsg_drv_init(FAR const char *cpuname, + FAR const char *devname, + enum net_lltype_e lltype) +{ + FAR struct net_rpmsg_drv_s *priv; + FAR struct net_driver_s *dev; + + /* Allocate the interface structure */ + + priv = kmm_zalloc(sizeof(*priv)); + if (priv == NULL) + { + return -ENOMEM; + } + + dev = &priv->dev; + + priv->cpuname = cpuname; + priv->devname = devname; + + /* Initialize the driver structure */ + + strcpy(dev->d_ifname, devname); + dev->d_ifup = net_rpmsg_drv_ifup; /* I/F up (new IP address) callback */ + dev->d_ifdown = net_rpmsg_drv_ifdown; /* I/F down callback */ + dev->d_txavail = net_rpmsg_drv_txavail; /* New TX data callback */ +#ifdef CONFIG_NET_IGMP + dev->d_addmac = net_rpmsg_drv_addmac; /* Add multicast MAC address */ + dev->d_rmmac = net_rpmsg_drv_rmmac; /* Remove multicast MAC address */ +#endif +#ifdef CONFIG_NETDEV_IOCTL + dev->d_ioctl = net_rpmsg_drv_ioctl; /* Handle network IOCTL commands */ +#endif + dev->d_private = priv; /* Used to recover private state from dev */ + + /* Create a watchdog for timing polling for transmissions */ + + priv->txpoll = wd_create(); /* Create periodic poll timer */ + DEBUGASSERT(priv->txpoll != NULL); + + /* Register the device with the openamp */ + + rpmsg_register_callback(dev, + net_rpmsg_drv_device_created, + net_rpmsg_drv_device_destroy, + NULL); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + netdev_register(dev, lltype); + return OK; +} diff --git a/drivers/rptun/Kconfig b/drivers/rptun/Kconfig new file mode 100644 index 00000000000..a640e73755b --- /dev/null +++ b/drivers/rptun/Kconfig @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if RPTUN + +config RPTUN_PRIORITY + int "rpturn thread priority" + default 224 + +config RPTUN_STACKSIZE + int "rptun stack size" + default 2048 + +endif diff --git a/drivers/rptun/Make.defs b/drivers/rptun/Make.defs new file mode 100644 index 00000000000..17c4953ed3f --- /dev/null +++ b/drivers/rptun/Make.defs @@ -0,0 +1,45 @@ +############################################################################ +# drivers/rptun/Make.defs +# +# Copyright (C) 2017 Pinecone Inc. All rights reserved. +# Author: Guiding Li +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +# Don't build anything if there is no RPTUN support + +ifeq ($(CONFIG_RPTUN),y) + +CSRCS += rptun.c + +DEPPATH += --dep-path rptun +VPATH += :rptun +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)rptun} +endif diff --git a/drivers/rptun/rptun.c b/drivers/rptun/rptun.c new file mode 100644 index 00000000000..256475a7c14 --- /dev/null +++ b/drivers/rptun/rptun.c @@ -0,0 +1,861 @@ +/**************************************************************************** + * drivers/rptun/rptun.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef ALIGN_UP +# define ALIGN_UP(s, a) (((s) + (a) - 1) & ~((a) - 1)) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rptun_priv_s +{ + FAR struct rptun_dev_s *dev; + struct remoteproc rproc; + struct rpmsg_virtio_device vdev; + struct rpmsg_virtio_shm_pool shm_pool; + struct metal_list bind; + struct metal_list node; + int pid; + bool started; +}; + +struct rptun_bind_s +{ + char name[RPMSG_NAME_SIZE]; + uint32_t dest; + struct metal_list node; +}; + +struct rptun_cb_s +{ + FAR void *priv; + rpmsg_dev_cb_t device_created; + rpmsg_dev_cb_t device_destroy; + rpmsg_bind_cb_t ns_bind; + struct metal_list node; +}; + +struct rptun_store_s +{ + int fd; + FAR char *buf; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static FAR struct remoteproc *rptun_init(FAR struct remoteproc *rproc, + FAR struct remoteproc_ops *ops, + FAR void *arg); +static void rptun_remove(FAR struct remoteproc *rproc); +static int rptun_mmap(FAR struct remoteproc *rproc, + FAR metal_phys_addr_t *pa, FAR metal_phys_addr_t *da, + FAR void **va, size_t size, unsigned int attribute, + FAR struct metal_io_region **io_); +static int rptun_start(FAR struct remoteproc *rproc); +static int rptun_stop(FAR struct remoteproc *rproc); +static int rptun_notify(FAR struct remoteproc *rproc, uint32_t id); + +static void rptun_ns_bind(FAR struct rpmsg_device *rdev, + FAR const char *name, uint32_t dest); + +static int rptun_dev_start(FAR struct remoteproc *rproc); +static int rptun_dev_stop(FAR struct remoteproc *rproc); +static int rptun_dev_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +static int rptun_store_open(FAR void *store_, FAR const char *path, + FAR const void **img_data); +static void rptun_store_close(FAR void *store_); +static int rptun_store_load(FAR void *store_, size_t offset, + size_t size, FAR const void **data, + metal_phys_addr_t pa, + FAR struct metal_io_region *io, + char is_blocking); + +static metal_phys_addr_t rptun_pa_to_da(FAR struct rptun_dev_s *dev, + metal_phys_addr_t pa); +static metal_phys_addr_t rptun_da_to_pa(FAR struct rptun_dev_s *dev, + metal_phys_addr_t da); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct remoteproc_ops g_rptun_ops = +{ + .init = rptun_init, + .remove = rptun_remove, + .mmap = rptun_mmap, + .start = rptun_start, + .stop = rptun_stop, + .notify = rptun_notify, +}; + +static const struct file_operations g_rptun_devops = +{ + .ioctl = rptun_dev_ioctl, +}; + +static struct image_store_ops g_rptun_storeops = +{ + .open = rptun_store_open, + .close = rptun_store_close, + .load = rptun_store_load, + .features = SUPPORT_SEEK, +}; + +static sem_t g_rptun_sem = SEM_INITIALIZER(1); + +static METAL_DECLARE_LIST(g_rptun_cb); +static METAL_DECLARE_LIST(g_rptun_priv); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int rptun_thread(int argc, FAR char *argv[]) +{ + FAR struct rptun_priv_s *priv; + sigset_t set; + int ret; + + priv = (FAR struct rptun_priv_s *)atoi(argv[1]); + + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + nxsig_procmask(SIG_BLOCK, &set, NULL); + + while (1) + { + ret = nxsig_timedwait(&set, NULL, NULL); + if (ret == SIGUSR1) + { + remoteproc_get_notification(&priv->rproc, RPTUN_NOTIFY_ALL); + } + } + + return 0; +} + +static int rptun_callback(FAR void *arg, uint32_t vqid) +{ + FAR struct rptun_priv_s *priv = arg; + + return nxsig_kill(priv->pid, SIGUSR1); +} + +static FAR struct remoteproc *rptun_init(FAR struct remoteproc *rproc, + FAR struct remoteproc_ops *ops, + FAR void *arg) +{ + rproc->ops = ops; + rproc->priv = arg; + + return rproc; +} + +static void rptun_remove(FAR struct remoteproc *rproc) +{ + rproc->priv = NULL; +} + +static int rptun_mmap(FAR struct remoteproc *rproc, + FAR metal_phys_addr_t *pa, FAR metal_phys_addr_t *da, + FAR void **va, size_t size, unsigned int attribute, + FAR struct metal_io_region **io_) +{ + FAR struct rptun_priv_s *priv = rproc->priv; + FAR struct metal_io_region *io = metal_io_get_region(); + + if (*pa != METAL_BAD_PHYS) + { + *da = rptun_pa_to_da(priv->dev, *pa); + *va = metal_io_phys_to_virt(io, *pa); + if (!*va) + { + return -RPROC_EINVAL; + } + } + else if (*da != METAL_BAD_PHYS) + { + *pa = rptun_da_to_pa(priv->dev, *da); + *va = metal_io_phys_to_virt(io, *pa); + if (!*va) + { + return -RPROC_EINVAL; + } + } + else if (*va) + { + *pa = metal_io_virt_to_phys(io, *va); + if (*pa == METAL_BAD_PHYS) + { + return -RPROC_EINVAL; + } + + *da = rptun_pa_to_da(priv->dev, *pa); + } + else + { + return -RPROC_EINVAL; + } + + if (io_) + { + *io_ = io; + } + + return 0; +} + +static int rptun_start(FAR struct remoteproc *rproc) +{ + FAR struct rptun_priv_s *priv = rproc->priv; + + if (RPTUN_IS_MASTER(priv->dev)) + { + return RPTUN_START(priv->dev); + } + + return 0; +} + +static int rptun_stop(FAR struct remoteproc *rproc) +{ + FAR struct rptun_priv_s *priv = rproc->priv; + + if (RPTUN_IS_MASTER(priv->dev)) + { + return RPTUN_STOP(priv->dev); + } + + return 0; +} + +static int rptun_notify(FAR struct remoteproc *rproc, uint32_t id) +{ + FAR struct rptun_priv_s *priv = rproc->priv; + + RPTUN_NOTIFY(priv->dev, RPTUN_NOTIFY_ALL); + + return 0; +} + +static void *rptun_get_priv_by_rdev(FAR struct rpmsg_device *rdev) +{ + struct rpmsg_virtio_device *rvdev; + struct virtio_device *vdev; + struct remoteproc_virtio *rpvdev; + struct remoteproc *rproc; + + rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); + vdev = rvdev->vdev; + if (!vdev) + { + return NULL; + } + + rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); + rproc = rpvdev->priv; + if (!rproc) + { + return NULL; + } + + return rproc->priv; +} + +static void rptun_ns_bind(FAR struct rpmsg_device *rdev, + FAR const char *name, uint32_t dest) +{ + FAR struct rptun_priv_s *priv = rptun_get_priv_by_rdev(rdev); + FAR struct rptun_bind_s *bind; + + bind = kmm_malloc(sizeof(struct rptun_bind_s)); + if (bind) + { + FAR struct metal_list *node; + FAR struct rptun_cb_s *cb; + + bind->dest = dest; + strncpy(bind->name, name, RPMSG_NAME_SIZE); + + nxsem_wait(&g_rptun_sem); + + metal_list_add_tail(&priv->bind, &bind->node); + + metal_list_for_each(&g_rptun_cb, node) + { + cb = metal_container_of(node, struct rptun_cb_s, node); + if (cb->ns_bind) + { + cb->ns_bind(rdev, cb->priv, name, dest); + } + } + + nxsem_post(&g_rptun_sem); + } +} + +static int rptun_dev_start(FAR struct remoteproc *rproc) +{ + FAR struct rptun_priv_s *priv = rproc->priv; + FAR struct virtio_device *vdev; + FAR struct rptun_rsc_s *rsc; + FAR struct metal_list *node; + FAR struct rptun_cb_s *cb; + unsigned int role = RPMSG_REMOTE; + int ret; + + if (RPTUN_GET_FIRMWARE(priv->dev)) + { + struct rptun_store_s store = + { + 0 + }; + + ret = remoteproc_load(rproc, RPTUN_GET_FIRMWARE(priv->dev), + &store, &g_rptun_storeops, NULL); + if (ret) + { + return ret; + } + + rsc = rproc->rsc_table; + } + else + { + rsc = RPTUN_GET_RESOURCE(priv->dev); + if (!rsc) + { + return -EINVAL; + } + + ret = remoteproc_set_rsc_table(rproc, (struct resource_table *)rsc, + sizeof(struct rptun_rsc_s)); + if (ret) + { + return ret; + } + } + + /* Update resource table on MASTER side */ + + if (RPTUN_IS_MASTER(priv->dev)) + { + uint32_t tbsz; + uint32_t v0sz; + uint32_t v1sz; + uint32_t shbufsz; + metal_phys_addr_t da0; + metal_phys_addr_t da1; + uint32_t align0; + uint32_t align1; + FAR void *va0; + FAR void *va1; + FAR void *shbuf; + + align0 = B2C(rsc->rpmsg_vring0.align); + align1 = B2C(rsc->rpmsg_vring1.align); + + tbsz = ALIGN_UP(sizeof(struct rptun_rsc_s), MAX(align0, align1)); + v0sz = vring_size(rsc->rpmsg_vring0.num, align0); + v1sz = vring_size(rsc->rpmsg_vring1.num, align1); + + va0 = (char *)rsc + tbsz; + va1 = (char *)rsc + tbsz + v0sz; + + da0 = da1 = METAL_BAD_PHYS; + + remoteproc_mmap(rproc, NULL, &da0, &va0, v0sz, 0, NULL); + remoteproc_mmap(rproc, NULL, &da1, &va1, v1sz, 0, NULL); + + rsc->rpmsg_vring0.da = da0; + rsc->rpmsg_vring1.da = da1; + + shbuf = (FAR char *)rsc + tbsz + v0sz + v1sz; + shbufsz = rsc->buf_size * + (rsc->rpmsg_vring0.num + rsc->rpmsg_vring1.num); + + rpmsg_virtio_init_shm_pool(&priv->shm_pool, shbuf, shbufsz); + + role = RPMSG_MASTER; + } + + /* Remote proc create */ + + vdev = remoteproc_create_virtio(rproc, 0, role, NULL); + if (!vdev) + { + return -ENOMEM; + } + + ret = rpmsg_init_vdev(&priv->vdev, vdev, rptun_ns_bind, + metal_io_get_region(), &priv->shm_pool); + if (ret) + { + remoteproc_remove_virtio(rproc, vdev); + return ret; + } + + /* Remote proc start */ + + ret = remoteproc_start(rproc); + if (ret) + { + remoteproc_remove_virtio(rproc, vdev); + return ret; + } + + nxsem_wait(&g_rptun_sem); + + /* Add priv to list */ + + metal_list_add_tail(&g_rptun_priv, &priv->node); + + /* Broadcast device_created to all registers */ + + metal_list_for_each(&g_rptun_cb, node) + { + cb = metal_container_of(node, struct rptun_cb_s, node); + if (cb->device_created) + { + cb->device_created(&priv->vdev.rdev, cb->priv); + } + } + + nxsem_post(&g_rptun_sem); + + /* Register callback to mbox for receving remote message */ + + RPTUN_REGISTER_CALLBACK(priv->dev, rptun_callback, priv); + + priv->started = true; + return 0; +} + +static int rptun_dev_stop(FAR struct remoteproc *rproc) +{ + FAR struct rptun_priv_s *priv = rproc->priv; + FAR struct metal_list *node; + FAR struct rptun_cb_s *cb; + + /* Unregister callback from mbox */ + + RPTUN_UNREGISTER_CALLBACK(priv->dev); + + nxsem_wait(&g_rptun_sem); + + /* Remove priv from list */ + + metal_list_del(&priv->node); + + /* Broadcast device_destroy to all registers */ + + metal_list_for_each(&g_rptun_cb, node) + { + cb = metal_container_of(node, struct rptun_cb_s, node); + if (cb->device_destroy) + { + cb->device_destroy(&priv->vdev.rdev, cb->priv); + } + } + + nxsem_post(&g_rptun_sem); + + /* Remote proc stop */ + + remoteproc_stop(rproc); + + /* Remote proc remove */ + + remoteproc_remove_virtio(rproc, priv->vdev.vdev); + rpmsg_deinit_vdev(&priv->vdev); + + /* Free bind list */ + + metal_list_for_each(&priv->bind, node) + { + struct rptun_bind_s *bind; + + bind = metal_container_of(node, struct rptun_bind_s, node); + kmm_free(bind); + } + + priv->started = false; + return 0; +} + +static int rptun_dev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct rptun_priv_s *priv = inode->i_private; + int ret = -ENOTTY; + + switch (cmd) + { + case RPTUNIOC_START: + if (!priv->started) + { + ret = rptun_dev_start(&priv->rproc); + } + break; + + case RPTUNIOC_STOP: + if (priv->started) + { + ret = rptun_dev_stop(&priv->rproc); + } + break; + } + + return ret; +} + +static int rptun_store_open(FAR void *store_, FAR const char *path, + FAR const void **img_data) +{ + FAR struct rptun_store_s *store = store_; + int len = 0x100; + + store->fd = open(path, O_RDONLY); + if (store->fd < 0) + { + return -EINVAL; + } + + store->buf = kmm_malloc(len); + if (!store->buf) + { + close(store->fd); + return -ENOMEM; + } + + *img_data = store->buf; + + return read(store->fd, store->buf, len); +} + +static void rptun_store_close(FAR void *store_) +{ + FAR struct rptun_store_s *store = store_; + + kmm_free(store->buf); + close(store->fd); +} + +static int rptun_store_load(FAR void *store_, size_t offset, + size_t size, FAR const void **data, + metal_phys_addr_t pa, + FAR struct metal_io_region *io, + char is_blocking) +{ + FAR struct rptun_store_s *store = store_; + FAR char *tmp; + + if (pa == METAL_BAD_PHYS) + { + tmp = kmm_realloc(store->buf, size); + if (!tmp) + { + return -ENOMEM; + } + + store->buf = tmp; + *data = tmp; + } + else + { + tmp = metal_io_phys_to_virt(io, pa); + if (!tmp) + { + return -EINVAL; + } + } + + lseek(store->fd, offset, SEEK_SET); + return read(store->fd, tmp, size); +} + +static metal_phys_addr_t rptun_pa_to_da(FAR struct rptun_dev_s *dev, + metal_phys_addr_t pa) +{ + FAR const struct rptun_addrenv_s *addrenv; + uint32_t i; + + addrenv = RPTUN_GET_ADDRENV(dev); + if (!addrenv) + { + return pa; + } + + for (i = 0; addrenv[i].size; i++) + { + if (pa - addrenv[i].pa < addrenv[i].size) + { + return addrenv[i].da + (pa - addrenv[i].pa); + } + } + + return pa; +} + +static metal_phys_addr_t rptun_da_to_pa(FAR struct rptun_dev_s *dev, + metal_phys_addr_t da) +{ + FAR const struct rptun_addrenv_s *addrenv; + uint32_t i; + + addrenv = RPTUN_GET_ADDRENV(dev); + if (!addrenv) + { + return da; + } + + for (i = 0; addrenv[i].size; i++) + { + if (da - addrenv[i].da < addrenv[i].size) + { + return addrenv[i].pa + (da - addrenv[i].da); + } + } + + return da; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +FAR const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev) +{ + FAR struct rptun_priv_s *priv = rptun_get_priv_by_rdev(rdev); + + return RPTUN_GET_CPUNAME(priv->dev); +} + +int rpmsg_register_callback(FAR void *priv_, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_bind_cb_t ns_bind) +{ + FAR struct metal_list *node; + FAR struct metal_list *bnode; + FAR struct rptun_cb_s *cb; + + cb = kmm_zalloc(sizeof(struct rptun_cb_s)); + if (!cb) + { + return -ENOMEM; + } + + cb->priv = priv_; + cb->device_created = device_created; + cb->device_destroy = device_destroy; + cb->ns_bind = ns_bind; + + nxsem_wait(&g_rptun_sem); + + metal_list_add_tail(&g_rptun_cb, &cb->node); + + metal_list_for_each(&g_rptun_priv, node) + { + struct rptun_priv_s *priv; + + priv = metal_container_of(node, struct rptun_priv_s, node); + if (device_created) + { + device_created(&priv->vdev.rdev, priv_); + } + + if (ns_bind) + { + metal_list_for_each(&priv->bind, bnode) + { + struct rptun_bind_s *bind; + + bind = metal_container_of(bnode, struct rptun_bind_s, node); + ns_bind(&priv->vdev.rdev, priv_, bind->name, bind->dest); + } + } + } + + nxsem_post(&g_rptun_sem); + + return 0; +} + +void rpmsg_unregister_callback(FAR void *priv_, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_bind_cb_t ns_bind) +{ + FAR struct metal_list *node; + FAR struct metal_list *pnode; + + nxsem_wait(&g_rptun_sem); + + metal_list_for_each(&g_rptun_cb, node) + { + struct rptun_cb_s *cb = NULL; + + cb = metal_container_of(node, struct rptun_cb_s, node); + if (cb->priv == priv_ && + cb->device_created == device_created && + cb->device_destroy == device_destroy && + cb->ns_bind == ns_bind) + { + if (device_destroy) + { + metal_list_for_each(&g_rptun_priv, pnode) + { + struct rptun_priv_s *priv; + + priv = metal_container_of(pnode, struct rptun_priv_s, node); + device_destroy(&priv->vdev.rdev, priv_); + } + } + + metal_list_del(&cb->node); + kmm_free(cb); + } + } + + nxsem_post(&g_rptun_sem); +} + +int rptun_initialize(FAR struct rptun_dev_s *dev) +{ + struct metal_init_params params = METAL_INIT_DEFAULTS; + FAR struct rptun_priv_s *priv; + char str[16]; + char name[16]; + FAR char *argv[2]; + int ret; + + ret = metal_init(¶ms); + if (ret) + { + return ret; + } + + priv = kmm_zalloc(sizeof(struct rptun_priv_s)); + if (priv == NULL) + { + return -ENOMEM; + } + + sprintf(name, "rptun%s", RPTUN_GET_CPUNAME(dev)); + + itoa((int)priv, str, 10); + argv[0] = str; + argv[1] = NULL; + ret = kthread_create(name, + CONFIG_RPTUN_PRIORITY, + CONFIG_RPTUN_STACKSIZE, + rptun_thread, + argv); + if (ret < 0) + { + kmm_free(priv); + return ret; + } + + priv->pid = ret; + priv->dev = dev; + + metal_list_init(&priv->bind); + + remoteproc_init(&priv->rproc, &g_rptun_ops, priv); + remoteproc_config(&priv->rproc, NULL); + + if (RPTUN_IS_AUTOSTART(dev)) + { + rptun_dev_start(&priv->rproc); + } + + sprintf(name, "/dev/rptun%s", RPTUN_GET_CPUNAME(dev)); + return register_driver(name, &g_rptun_devops, 0666, priv); +} + +int rptun_boot(FAR const char *cpuname) +{ + struct file filep; + char name[16]; + int ret; + + if (!cpuname) + { + return -EINVAL; + } + + sprintf(name, "/dev/rptun%s", cpuname); + + ret = file_open(&filep, name, 0, 0); + if (ret) + { + return ret; + } + + ret = file_ioctl(&filep, RPTUNIOC_START, 0); + file_close(&filep); + + return ret; +} diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d566f724587..a6e44d6033d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -56,6 +56,21 @@ config MCU_SERIAL bool default n +config RPMSG_UART + bool "UART rpmsg support" + default n + depends on OPENAMP + select ARCH_HAVE_SERIAL_TERMIOS + select SERIAL_RXDMA + select SERIAL_TXDMA + select SERIAL_REMOVABLE + select SERIAL_IFLOWCONTROL + +config RPMSG_SERIALINIT + bool "Add dummy up_serialinit for UART rpmsg" + default !16550_UART && !CMSDK_UART && !MCU_SERIAL + depends on RPMSG_UART + # # Standard serial driver configuration # diff --git a/drivers/serial/Make.defs b/drivers/serial/Make.defs index 5789c226080..36babbeef28 100644 --- a/drivers/serial/Make.defs +++ b/drivers/serial/Make.defs @@ -47,6 +47,10 @@ ifeq ($(CONFIG_16550_UART),y) CSRCS += uart_16550.c endif +ifeq ($(CONFIG_RPMSG_UART),y) + CSRCS += uart_rpmsg.c +endif + # termios support ifeq ($(CONFIG_SERIAL_TERMIOS),y) diff --git a/drivers/serial/uart_rpmsg.c b/drivers/serial/uart_rpmsg.c new file mode 100644 index 00000000000..7c76f79f99d --- /dev/null +++ b/drivers/serial/uart_rpmsg.c @@ -0,0 +1,543 @@ +/**************************************************************************** + * drivers/serial/uart_rpmsg.c + * Serial driver for rpmsg UART + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#define UART_RPMSG_DEV_CONSOLE "/dev/console" +#define UART_RPMSG_DEV_PREFIX "/dev/tty" +#define UART_RPMSG_EPT_PREFIX "rpmsg-tty" + +#define UART_RPMSG_TTY_WRITE 0 +#define UART_RPMSG_TTY_WAKEUP 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +begin_packed_struct struct uart_rpmsg_header_s +{ + uint32_t command : 31; + uint32_t response : 1; + int32_t result; + uint64_t cookie; +} end_packed_struct; + +begin_packed_struct struct uart_rpmsg_write_s +{ + struct uart_rpmsg_header_s header; + uint32_t count; + uint32_t resolved; + char data[0]; +} end_packed_struct; + +begin_packed_struct struct uart_rpmsg_wakeup_s +{ + struct uart_rpmsg_header_s header; +} end_packed_struct; + +struct uart_rpmsg_priv_s +{ + struct rpmsg_endpoint ept; + FAR const char *devname; + FAR const char *cpuname; + FAR void *recv_data; + bool last_upper; +#ifdef CONFIG_SERIAL_TERMIOS + struct termios termios; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int uart_rpmsg_setup(FAR struct uart_dev_s *dev); +static void uart_rpmsg_shutdown(FAR struct uart_dev_s *dev); +static int uart_rpmsg_attach(FAR struct uart_dev_s *dev); +static void uart_rpmsg_detach(FAR struct uart_dev_s *dev); +static int uart_rpmsg_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static void uart_rpmsg_rxint(FAR struct uart_dev_s *dev, bool enable); +static bool uart_rpmsg_rxflowcontrol(FAR struct uart_dev_s *dev, + unsigned int nbuffered, bool upper); +static void uart_rpmsg_dmasend(FAR struct uart_dev_s *dev); +static void uart_rpmsg_dmareceive(FAR struct uart_dev_s *dev); +static void uart_rpmsg_dmarxfree(FAR struct uart_dev_s *dev); +static void uart_rpmsg_dmatxavail(FAR struct uart_dev_s *dev); +static void uart_rpmsg_send(FAR struct uart_dev_s *dev, int ch); +static void uart_rpmsg_txint(FAR struct uart_dev_s *dev, bool enable); +static bool uart_rpmsg_txready(FAR struct uart_dev_s *dev); +static bool uart_rpmsg_txempty(FAR struct uart_dev_s *dev); +static void uart_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_); +static void uart_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_); +static int uart_rpmsg_ept_cb(struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv_); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_rpmsg_ops = +{ + .setup = uart_rpmsg_setup, + .shutdown = uart_rpmsg_shutdown, + .attach = uart_rpmsg_attach, + .detach = uart_rpmsg_detach, + .ioctl = uart_rpmsg_ioctl, + .rxint = uart_rpmsg_rxint, + .rxflowcontrol = uart_rpmsg_rxflowcontrol, + .dmasend = uart_rpmsg_dmasend, + .dmareceive = uart_rpmsg_dmareceive, + .dmarxfree = uart_rpmsg_dmarxfree, + .dmatxavail = uart_rpmsg_dmatxavail, + .send = uart_rpmsg_send, + .txint = uart_rpmsg_txint, + .txready = uart_rpmsg_txready, + .txempty = uart_rpmsg_txempty, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int uart_rpmsg_setup(FAR struct uart_dev_s *dev) +{ + return OK; +} + +static void uart_rpmsg_shutdown(FAR struct uart_dev_s *dev) +{ +} + +static int uart_rpmsg_attach(FAR struct uart_dev_s *dev) +{ + return OK; +} + +static void uart_rpmsg_detach(FAR struct uart_dev_s *dev) +{ +} + +static int uart_rpmsg_ioctl(FAR struct file *filep, int cmd, + unsigned long arg) +{ + int ret = -ENOTTY; + +#ifdef CONFIG_SERIAL_TERMIOS + struct uart_dev_s *dev = filep->f_inode->i_private; + struct uart_rpmsg_priv_s *priv = dev->priv; + + switch (cmd) + { + case TCGETS: + { + FAR struct termios *termiosp = (struct termios *)arg; + + if (termiosp) + { + *termiosp = priv->termios; + ret = OK; + } + else + { + ret = -EINVAL; + } + } + break; + + case TCSETS: + { + FAR struct termios *termiosp = (struct termios *)arg; + + if (termiosp) + { + priv->termios = *termiosp; + ret = OK; + } + else + { + ret = -EINVAL; + } + } + break; + } +#endif + + return ret; +} + +static void uart_rpmsg_rxint(FAR struct uart_dev_s *dev, bool enable) +{ +} + +static bool uart_rpmsg_rxflowcontrol(FAR struct uart_dev_s *dev, + unsigned int nbuffered, bool upper) +{ + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + FAR struct uart_rpmsg_wakeup_s msg; + + if (!upper && upper != priv->last_upper) + { + memset(&msg, 0, sizeof(msg)); + + msg.header.command = UART_RPMSG_TTY_WAKEUP; + if (is_rpmsg_ept_ready(&priv->ept)) + { + rpmsg_send(&priv->ept, &msg, sizeof(msg)); + } + } + + priv->last_upper = upper; + return false; +} + +static void uart_rpmsg_dmasend(FAR struct uart_dev_s *dev) +{ + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + FAR struct uart_dmaxfer_s *xfer = &dev->dmatx; + FAR struct uart_rpmsg_write_s *msg; + size_t len = xfer->length + xfer->nlength; + uint32_t space; + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + dev->dmatx.length = 0; + return; + } + + memset(msg, 0, sizeof(*msg)); + + space = C2B(space - sizeof(*msg)); + + if (len > space) + { + len = space; + } + + if (len > xfer->length) + { + cmem2bmem(msg->data, 0, xfer->buffer, xfer->length); + cmem2bmem(msg->data + B2C_OFF(xfer->length), B2C_REM(xfer->length), + xfer->nbuffer, len - xfer->length); + } + else + { + cmem2bmem(msg->data, 0, xfer->buffer, len); + } + + msg->count = len; + msg->header.command = UART_RPMSG_TTY_WRITE; + msg->header.result = -ENXIO; + msg->header.cookie = (uintptr_t)dev; + + rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) + B2C(len)); +} + +static void uart_rpmsg_dmareceive(FAR struct uart_dev_s *dev) +{ + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + FAR struct uart_dmaxfer_s *xfer = &dev->dmarx; + FAR struct uart_rpmsg_write_s *msg = priv->recv_data; + uint32_t len = msg->count; + size_t space = xfer->length + xfer->nlength; + + if (len > space) + { + len = space; + } + + if (len > xfer->length) + { + bmem2cmem(xfer->buffer, msg->data, 0, xfer->length); + bmem2cmem(xfer->nbuffer, msg->data + B2C_OFF(xfer->length), + B2C_REM(xfer->length), len - xfer->length); + } + else + { + bmem2cmem(xfer->buffer, msg->data, 0, len); + } + + xfer->nbytes = len; + uart_recvchars_done(dev); + + msg->header.result = len; + + if (len != msg->count) + { + uart_rpmsg_rxflowcontrol(dev, 0, true); + } +} + +static void uart_rpmsg_dmarxfree(FAR struct uart_dev_s *dev) +{ +} + +static void uart_rpmsg_dmatxavail(FAR struct uart_dev_s *dev) +{ + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + + if (is_rpmsg_ept_ready(&priv->ept) && dev->dmatx.length == 0) + { + uart_xmitchars_dma(dev); + } +} + +static void uart_rpmsg_send(FAR struct uart_dev_s *dev, int ch) +{ + int nexthead; + + nexthead = dev->xmit.head + 1; + if (nexthead >= dev->xmit.size) + { + nexthead = 0; + } + + if (nexthead != dev->xmit.tail) + { + /* No.. not full. Add the character to the TX buffer and return. */ + + dev->xmit.buffer[dev->xmit.head] = ch; + dev->xmit.head = nexthead; + } + + uart_rpmsg_dmatxavail(dev); +} + +static void uart_rpmsg_txint(FAR struct uart_dev_s *dev, bool enable) +{ +} + +static bool uart_rpmsg_txready(FAR struct uart_dev_s *dev) +{ + int nexthead; + + nexthead = dev->xmit.head + 1; + if (nexthead >= dev->xmit.size) + { + nexthead = 0; + } + + return nexthead != dev->xmit.tail; +} + +static bool uart_rpmsg_txempty(FAR struct uart_dev_s *dev) +{ + return true; +} + +static void uart_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct uart_dev_s *dev = priv_; + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + char eptname[RPMSG_NAME_SIZE]; + + if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + priv->ept.priv = dev; + sprintf(eptname, "%s%s", UART_RPMSG_EPT_PREFIX, priv->devname); + rpmsg_create_ept(&priv->ept, rdev, eptname, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + uart_rpmsg_ept_cb, NULL); + } +} + +static void uart_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct uart_dev_s *dev = priv_; + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + + if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + rpmsg_destroy_ept(&priv->ept); + } +} + +static int uart_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv_) +{ + FAR struct uart_dev_s *dev = priv_; + FAR struct uart_rpmsg_header_s *header = data; + FAR struct uart_rpmsg_write_s *msg = data; + + if (header->response) + { + /* Get write-cmd reponse, this tell how many data have sent */ + + dev->dmatx.nbytes = header->result; + if (header->result < 0) + { + dev->dmatx.nbytes = 0; + } + + uart_xmitchars_done(dev); + + /* If have sent some data succeed, then continue send */ + + if (msg->count == header->result) + { + uart_rpmsg_dmatxavail(dev); + } + } + else if (header->command == UART_RPMSG_TTY_WRITE) + { + FAR struct uart_rpmsg_priv_s *priv = dev->priv; + + /* Get write-cmd, there are some data, we need receive them */ + + priv->recv_data = data; + uart_recvchars_dma(dev); + priv->recv_data = NULL; + + header->response = 1; + rpmsg_send(ept, msg, sizeof(*msg)); + } + else if (header->command == UART_RPMSG_TTY_WAKEUP) + { + /* Remote core have space, then wakeup current core, continue send */ + + uart_rpmsg_dmatxavail(dev); + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int uart_rpmsg_init(FAR const char *cpuname, FAR const char *devname, + int buf_size, bool isconsole) +{ + FAR struct uart_rpmsg_priv_s *priv; + FAR struct uart_dev_s *dev; + char dev_name[32]; + int ret = -ENOMEM; + + dev = kmm_zalloc(sizeof(struct uart_dev_s)); + if (!dev) + { + return ret; + } + + dev->ops = &g_uart_rpmsg_ops; + dev->isconsole = isconsole; + dev->recv.size = buf_size; + dev->xmit.size = buf_size; + + dev->recv.buffer = kmm_malloc(dev->recv.size); + if (!dev->recv.buffer) + { + goto fail; + } + + dev->xmit.buffer = kmm_malloc(dev->xmit.size); + if (!dev->xmit.buffer) + { + goto fail; + } + + priv = kmm_zalloc(sizeof(struct uart_rpmsg_priv_s)); + if (!priv) + { + goto fail; + } + + priv->cpuname = cpuname; + priv->devname = devname; + + dev->priv = priv; + + ret = rpmsg_register_callback(dev, + uart_rpmsg_device_created, + uart_rpmsg_device_destroy, + NULL); + if (ret < 0) + { + goto fail; + } + + sprintf(dev_name, "%s%s", UART_RPMSG_DEV_PREFIX, devname); + uart_register(dev_name, dev); + + if (dev->isconsole) + { + uart_register(UART_RPMSG_DEV_CONSOLE, dev); + } + + return OK; + +fail: + kmm_free(dev->recv.buffer); + kmm_free(dev->xmit.buffer); + kmm_free(dev->priv); + kmm_free(dev); + + return ret; +} + +#ifdef CONFIG_RPMSG_SERIALINIT +/* Dummy function to make linker happy */ + +void up_earlyserialinit(void) +{ +} + +void up_serialinit(void) +{ +} +#endif /* CONFIG_RPMSG_SERIALINIT */ diff --git a/drivers/syslog/Kconfig b/drivers/syslog/Kconfig index 8e9e179c2d0..4c21df11cc8 100644 --- a/drivers/syslog/Kconfig +++ b/drivers/syslog/Kconfig @@ -172,6 +172,14 @@ config SYSLOG_CONSOLE ---help--- Use the system console as a SYSLOG output device. +config SYSLOG_RPMSG + bool "Log to RPMSG" + depends on OPENAMP + depends on SCHED_WORKQUEUE + select SYSLOG_WRITE + ---help--- + Use the rpmsg as a SYSLOG output device, send message to remote proc. + config SYSLOG_NONE bool "No SYSLOG device" ---help--- @@ -180,6 +188,18 @@ config SYSLOG_NONE endchoice +config SYSLOG_RPMSG_WORK_DELAY + int "SYSLOG RPMSG work delay(ms)" + default 100 + depends on SYSLOG_RPMSG + +config SYSLOG_RPMSG_SERVER + bool "Enable RPMSG server for SYSLOG" + default n + depends on OPENAMP + ---help--- + Use rpmsg to receive message from remote proc. + config SYSLOG_FILE bool "Syslog file output" default n diff --git a/drivers/syslog/Make.defs b/drivers/syslog/Make.defs index f3634498390..c34a3f245ca 100644 --- a/drivers/syslog/Make.defs +++ b/drivers/syslog/Make.defs @@ -84,6 +84,14 @@ ifeq ($(CONFIG_SYSLOG_CHARDEV),y) CSRCS += syslog_chardev.c endif +ifeq ($(CONFIG_SYSLOG_RPMSG),y) + CSRCS += syslog_rpmsg.c +endif + +ifeq ($(CONFIG_SYSLOG_RPMSG_SERVER),y) + CSRCS += syslog_rpmsg_server.c +endif + ifeq ($(CONFIG_CONSOLE_SYSLOG),y) CSRCS += syslog_console.c endif diff --git a/drivers/syslog/syslog_rpmsg.c b/drivers/syslog/syslog_rpmsg.c new file mode 100644 index 00000000000..6f6a157a0cc --- /dev/null +++ b/drivers/syslog/syslog_rpmsg.c @@ -0,0 +1,417 @@ +/**************************************************************************** + * drivers/syslog/syslog_rpmsg.c + * Syslog driver for rpmsg syslog + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "syslog.h" +#include "syslog_rpmsg.h" + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#define SYSLOG_RPMSG_WORK_DELAY MSEC2TICK(CONFIG_SYSLOG_RPMSG_WORK_DELAY) + +#define SYSLOG_RPMSG_COUNT(h, t, size) ((B2C_OFF(h)>=(t)) ? \ + B2C_OFF(h)-(t) : \ + (size)-((t)-B2C_OFF(h))) +#define SYSLOG_RPMSG_SPACE(h, t, size) ((size) - 1 - SYSLOG_RPMSG_COUNT(h, t, size)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct syslog_rpmsg_s +{ + volatile size_t head; /* The head index (where data is added) */ + volatile size_t tail; /* The tail index (where data is removed) */ + size_t size; /* Size of the RAM buffer */ + FAR char *buffer; /* Circular RAM buffer */ + struct work_s work; /* Used for deferred callback work */ + + struct rpmsg_endpoint ept; + FAR const char *cpuname; + bool suspend; + bool transfer; /* The transfer flag */ + ssize_t trans_len; /* The data length when transfer */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void syslog_rpmsg_work(FAR void *priv_); +static void syslog_rpmsg_putc(FAR struct syslog_rpmsg_s *priv, int ch, + bool last); +static int syslog_rpmsg_flush(void); +static ssize_t syslog_rpmsg_write(FAR const char *buffer, size_t buflen); +static void syslog_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_); +static void syslog_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_); +static int syslog_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv_); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct syslog_rpmsg_s g_syslog_rpmsg; + +static const struct syslog_channel_s g_syslog_rpmsg_channel = +{ + up_putc, + up_putc, + syslog_rpmsg_flush, + syslog_rpmsg_write, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void syslog_rpmsg_work(FAR void *priv_) +{ + FAR struct syslog_rpmsg_transfer_s *msg = NULL; + FAR struct syslog_rpmsg_s *priv = priv_; + irqstate_t flags; + uint32_t space; + size_t len; + size_t len_end; + + if (is_rpmsg_ept_ready(&priv->ept)) + { + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, false); + } + + if (!msg) + { + work_queue(HPWORK, &priv->work, syslog_rpmsg_work, priv, + SYSLOG_RPMSG_WORK_DELAY); + return; + } + + memset(msg, 0, sizeof(*msg)); + + flags = enter_critical_section(); + + if (B2C_REM(priv->head)) + { + priv->head += C2B(1) - B2C_REM(priv->head); + } + + space -= sizeof(*msg); + len = SYSLOG_RPMSG_COUNT(priv->head, priv->tail, priv->size); + len_end = priv->size - priv->tail; + + if (len > space) + { + len = space; + } + + if (len > len_end) + { + memcpy(msg->data, &priv->buffer[priv->tail], len_end); + memcpy(msg->data + len_end, priv->buffer, len - len_end); + } + else + { + memcpy(msg->data, &priv->buffer[priv->tail], len); + } + + priv->trans_len = len; + priv->transfer = true; + + leave_critical_section(flags); + + msg->header.command = SYSLOG_RPMSG_TRANSFER; + msg->count = C2B(len); + rpmsg_send_nocopy(&priv->ept, msg, sizeof(*msg) + len); +} + +static void syslog_rpmsg_putc(FAR struct syslog_rpmsg_s *priv, int ch, + bool last) +{ + if (B2C_REM(priv->head) == 0) + { + priv->buffer[B2C_OFF(priv->head)] = 0; + } + + priv->buffer[B2C_OFF(priv->head)] |= (ch & 0xff) << (8 * B2C_REM(priv->head)); + + priv->head += 1; + if (priv->head >= C2B(priv->size)) + { + priv->head = 0; + } + + /* Allow overwrite */ + + if (priv->head == C2B(priv->tail)) + { + priv->buffer[priv->tail] = 0; + + priv->tail += 1; + if (priv->tail >= priv->size) + { + priv->tail = 0; + } + + if (priv->transfer) + { + priv->trans_len--; + } + } + + if (last && !priv->suspend && !priv->transfer) + { + clock_t delay = SYSLOG_RPMSG_WORK_DELAY; + size_t space = SYSLOG_RPMSG_SPACE(priv->head, priv->tail, priv->size); + + /* Start work immediately when data more then 75% and meet '\n' */ + + if (space < priv->size / 4 && ch == '\n') + { + delay = 0; + } + + work_queue(HPWORK, &priv->work, syslog_rpmsg_work, priv, delay); + } +} + +static int syslog_rpmsg_flush(void) +{ + FAR struct syslog_rpmsg_s *priv = &g_syslog_rpmsg; + + work_queue(HPWORK, &priv->work, syslog_rpmsg_work, priv, 0); + return OK; +} + +static ssize_t syslog_rpmsg_write(FAR const char *buffer, size_t buflen) +{ + FAR struct syslog_rpmsg_s *priv = &g_syslog_rpmsg; + irqstate_t flags; + size_t nwritten; + + flags = enter_critical_section(); + for (nwritten = 1; nwritten <= buflen; nwritten++) + { + syslog_rpmsg_putc(priv, *buffer++, nwritten == buflen); + } + + leave_critical_section(flags); + + return buflen; +} + +static void syslog_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct syslog_rpmsg_s *priv = priv_; + int ret; + + if (priv->buffer && strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + priv->ept.priv = priv; + + ret = rpmsg_create_ept(&priv->ept, rdev, SYSLOG_RPMSG_EPT_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + syslog_rpmsg_ept_cb, NULL); + if (ret == 0) + { + work_queue(HPWORK, &priv->work, + syslog_rpmsg_work, priv, SYSLOG_RPMSG_WORK_DELAY); + } + } +} + +static void syslog_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct syslog_rpmsg_s *priv = priv_; + + if (priv->buffer && strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + rpmsg_destroy_ept(&priv->ept); + } +} + +static int syslog_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv_) +{ + FAR struct syslog_rpmsg_s *priv = priv_; + FAR struct syslog_rpmsg_header_s *header = data; + + if (header->command == SYSLOG_RPMSG_SUSPEND) + { + work_cancel(HPWORK, &priv->work); + priv->suspend = true; + } + else if (header->command == SYSLOG_RPMSG_RESUME) + { + priv->suspend = false; + work_queue(HPWORK, &priv->work, + syslog_rpmsg_work, priv, SYSLOG_RPMSG_WORK_DELAY); + } + else if (header->command == SYSLOG_RPMSG_TRANSFER_DONE) + { + irqstate_t flags; + ssize_t len_end; + + flags = enter_critical_section(); + + if (priv->trans_len > 0) + { + len_end = priv->size - priv->tail; + + if (priv->trans_len > len_end) + { + memset(&priv->buffer[priv->tail], 0, len_end); + memset(priv->buffer, 0, priv->trans_len - len_end); + } + else + { + memset(&priv->buffer[priv->tail], 0, priv->trans_len); + } + + priv->tail += priv->trans_len; + if (priv->tail >= priv->size) + { + priv->tail -= priv->size; + } + } + + priv->transfer = false; + + if (SYSLOG_RPMSG_COUNT(priv->head, priv->tail, priv->size)) + { + work_queue(HPWORK, &priv->work, syslog_rpmsg_work, priv, 0); + } + + leave_critical_section(flags); + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int up_putc(int ch) +{ + FAR struct syslog_rpmsg_s *priv = &g_syslog_rpmsg; + irqstate_t flags; + + flags = enter_critical_section(); + syslog_rpmsg_putc(priv, ch, true); + leave_critical_section(flags); + + return ch; +} + +int syslog_rpmsg_init_early(FAR const char *cpuname, FAR void *buffer, + size_t size) +{ + FAR struct syslog_rpmsg_s *priv = &g_syslog_rpmsg; + char prev, cur; + size_t i; + size_t j; + + priv->cpuname = cpuname; + priv->buffer = buffer; + priv->size = size; + + prev = (priv->buffer[size - 1] >> (CHAR_BIT - 8)) & 0xff; + + for (i = 0; i < size; i++) + { + for (j = 0; j * 8 < CHAR_BIT; j++) + { + cur = (priv->buffer[i] >> j * 8) & 0xff; + + if (!isascii(cur)) + { + goto out; + } + + if (prev && !cur) + { + priv->head = C2B(i) + j; + } + + if (!prev && cur) + { + priv->tail = i; + } + + prev = cur; + } + } + +out: + if (i != size) + { + priv->head = priv->tail = 0; + memset(priv->buffer, 0, size); + } + + return syslog_channel(&g_syslog_rpmsg_channel); +} + +int syslog_rpmsg_init(void) +{ + return rpmsg_register_callback(&g_syslog_rpmsg, + syslog_rpmsg_device_created, + syslog_rpmsg_device_destroy, + NULL); +} diff --git a/drivers/syslog/syslog_rpmsg.h b/drivers/syslog/syslog_rpmsg.h new file mode 100644 index 00000000000..89e6f09a14f --- /dev/null +++ b/drivers/syslog/syslog_rpmsg.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * drivers/syslog/syslog_rpmsg.h + * Syslog driver for rpmsg syslog + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __DRIVERS_SYSLOG_SYSLOG_RPMSG_H +#define __DRIVERS_SYSLOG_SYSLOG_RPMSG_H + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#define SYSLOG_RPMSG_EPT_NAME "rpmsg-syslog" + +#define SYSLOG_RPMSG_TRANSFER 0 +#define SYSLOG_RPMSG_TRANSFER_DONE 1 +#define SYSLOG_RPMSG_SUSPEND 2 +#define SYSLOG_RPMSG_RESUME 3 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +begin_packed_struct struct syslog_rpmsg_header_s +{ + uint32_t command; + int32_t result; +} end_packed_struct; + +begin_packed_struct struct syslog_rpmsg_transfer_s +{ + struct syslog_rpmsg_header_s header; + int32_t count; + char data[0]; +} end_packed_struct; + +#endif /* __DRIVERS_SYSLOG_SYSLOG_RPMSG_H */ diff --git a/drivers/syslog/syslog_rpmsg_server.c b/drivers/syslog/syslog_rpmsg_server.c new file mode 100644 index 00000000000..5fa3195c52f --- /dev/null +++ b/drivers/syslog/syslog_rpmsg_server.c @@ -0,0 +1,235 @@ +/**************************************************************************** + * drivers/syslog/syslog_rpmsg_server.c + * Syslog driver for rpmsg syslog server + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "syslog.h" +#include "syslog_rpmsg.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SYSLOG_RPMSG_MAXLEN 256 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct syslog_rpmsg_server_s +{ + struct rpmsg_endpoint ept; + FAR char *tmpbuf; + unsigned int nextpos; + unsigned int alloced; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void syslog_rpmsg_write(FAR const char *buf1, size_t len1, + FAR const char *buf2, size_t len2); +static void syslog_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, + FAR void *priv_, FAR const char *name, + uint32_t dest); +static void syslog_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept); +static int syslog_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv_); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void syslog_rpmsg_write(FAR const char *buf1, size_t len1, + FAR const char *buf2, size_t len2) +{ + FAR const char *nl; + size_t len; + + nl = memchr(buf2, '\n', len2); + DEBUGASSERT(nl != NULL); + len = nl + 1 - buf2; + + if (len1 + len <= SYSLOG_RPMSG_MAXLEN) + { + char tmpbuf[SYSLOG_RPMSG_MAXLEN]; + + /* Ensure each syslog_write's buffer end with '\n' */ + + memcpy(tmpbuf, buf1, len1); + memcpy(tmpbuf + len1, buf2, len); + syslog_write(tmpbuf, len1 + len); + + if (len < len2) + { + syslog_write(nl + 1, len2 - len); + } + } + else + { + /* Give up, the merge buffer is too big */ + + syslog_write(buf1, len1); + syslog_write(buf2, len2); + } +} + +static void syslog_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, + FAR void *priv_, FAR const char *name, + uint32_t dest) +{ + FAR struct syslog_rpmsg_server_s *priv; + int ret; + + if (strcmp(name, SYSLOG_RPMSG_EPT_NAME)) + { + return; + } + + priv = kmm_zalloc(sizeof(struct syslog_rpmsg_server_s)); + if (!priv) + { + return; + } + + priv->ept.priv = priv; + + ret = rpmsg_create_ept(&priv->ept, rdev, SYSLOG_RPMSG_EPT_NAME, + RPMSG_ADDR_ANY, dest, + syslog_rpmsg_ept_cb, syslog_rpmsg_ns_unbind); + if (ret) + { + kmm_free(priv); + } +} + +static void syslog_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept) +{ + FAR struct syslog_rpmsg_server_s *priv = ept->priv; + + if (priv->nextpos) + { + syslog_rpmsg_write(priv->tmpbuf, priv->nextpos, "\n", 1); + } + + rpmsg_destroy_ept(ept); + + kmm_free(priv->tmpbuf); + kmm_free(priv); +} + +static int syslog_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv_) +{ + FAR struct syslog_rpmsg_server_s *priv = priv_; + FAR struct syslog_rpmsg_header_s *header = data; + + if (header->command == SYSLOG_RPMSG_TRANSFER) + { + FAR struct syslog_rpmsg_transfer_s *msg = data; + struct syslog_rpmsg_header_s done; + unsigned int copied = msg->count; + unsigned int printed = 0; + FAR const char *nl; + + nl = memrchr(msg->data, '\n', msg->count); + if (nl != NULL) + { + printed = nl + 1 - msg->data; + copied = msg->count - printed; + + if (priv->nextpos) + { + syslog_rpmsg_write(priv->tmpbuf, priv->nextpos, msg->data, printed); + priv->nextpos = 0; + } + else + { + syslog_write(msg->data, printed); + } + } + + if (copied != 0) + { + unsigned int newsize = priv->nextpos + copied; + if (newsize > priv->alloced) + { + char *newbuf = kmm_realloc(priv->tmpbuf, newsize); + if (newbuf != NULL) + { + priv->tmpbuf = newbuf; + priv->alloced = newsize; + } + else + { + copied = priv->alloced - priv->nextpos; + } + } + + memcpy(priv->tmpbuf + priv->nextpos, msg->data + printed, copied); + priv->nextpos += copied; + } + + done.command = SYSLOG_RPMSG_TRANSFER_DONE; + done.result = printed + copied; + rpmsg_send(ept, &done, sizeof(done)); + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int syslog_rpmsg_server_init(void) +{ + return rpmsg_register_callback(NULL, + NULL, + NULL, + syslog_rpmsg_ns_bind); +} diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig index 6cf67647171..82ad5440975 100644 --- a/drivers/timers/Kconfig +++ b/drivers/timers/Kconfig @@ -279,6 +279,14 @@ config MCP794XX_I2C_FREQUENCY range 1 400000 endif # RTC_MCP794XX + +config RTC_RPMSG + bool "Rpmsg RTC Driver" + default n + depends on OPENAMP + depends on RTC_EXTERNAL + select ARCH_HAVE_RTC_SUBSECONDS + endif # RTC menuconfig WATCHDOG diff --git a/drivers/timers/Make.defs b/drivers/timers/Make.defs index 7c8aa8e6e97..cdde9698cfe 100644 --- a/drivers/timers/Make.defs +++ b/drivers/timers/Make.defs @@ -87,6 +87,12 @@ ifeq ($(CONFIG_RTC_MCP794XX),y) TMRVPATH = :timers endif +ifeq ($(CONFIG_RTC_RPMSG),y) + CSRCS += rpmsg_rtc.c + TMRDEPPATH = --dep-path timers + TMRVPATH = :timers +endif + ifeq ($(CONFIG_RTC_ARCH),y) CSRCS += arch_rtc.c TMRDEPPATH = --dep-path timers diff --git a/drivers/timers/rpmsg_rtc.c b/drivers/timers/rpmsg_rtc.c new file mode 100644 index 00000000000..38c2665e663 --- /dev/null +++ b/drivers/timers/rpmsg_rtc.c @@ -0,0 +1,427 @@ +/**************************************************************************** + * drivers/timers/rpmsg_rtc.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#define RPMSG_RTC_EPT_NAME "rpmsg-rtc" + +#define RPMSG_RTC_SET 0 +#define RPMSG_RTC_GET 1 +#define RPMSG_RTC_ALARM_SET 2 +#define RPMSG_RTC_ALARM_CANCEL 3 +#define RPMSG_RTC_ALARM_FIRE 4 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +begin_packed_struct struct rpmsg_rtc_header_s +{ + uint32_t command; + int32_t result; + uint64_t cookie; +} end_packed_struct; + +begin_packed_struct struct rpmsg_rtc_set_s +{ + struct rpmsg_rtc_header_s header; + int64_t sec; + int32_t nsec; +} end_packed_struct; + +#define rpmsg_rtc_get_s rpmsg_rtc_set_s + +begin_packed_struct struct rpmsg_rtc_alarm_set_s +{ + struct rpmsg_rtc_header_s header; + int64_t sec; + int32_t nsec; + int32_t id; +} end_packed_struct; + +begin_packed_struct struct rpmsg_rtc_alarm_cancel_s +{ + struct rpmsg_rtc_header_s header; + int32_t id; +} end_packed_struct; + +#define rpmsg_rtc_alarm_fire_s rpmsg_rtc_alarm_cancel_s + +struct rpmsg_rtc_cookie_s +{ + FAR struct rpmsg_rtc_header_s *msg; + sem_t sem; +}; + +/* This is the private type for the RTC state. It must be cast compatible + * with struct rtc_lowerhalf_s. + */ + +struct rpmsg_rtc_lowerhalf_s +{ + /* This is the contained reference to the read-only, lower-half + * operations vtable (which may lie in FLASH or ROM) + */ + + FAR const struct rtc_ops_s *ops; + + /* Data following is private to this driver and not visible outside of + * this file. + */ + + struct rpmsg_endpoint ept; + FAR const char *cpuname; + +#ifdef CONFIG_RTC_ALARM + struct lower_setalarm_s alarminfo[CONFIG_RTC_NALARMS]; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void rpmsg_rtc_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv); +static void rpmsg_rtc_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv); +static void rpmsg_rtc_alarm_fire_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int rpmsg_rtc_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv); + +static int rpmsg_rtc_send_recv(FAR struct rpmsg_rtc_lowerhalf_s *lower, + uint32_t command, + FAR struct rpmsg_rtc_header_s *msg, int len); +static int rpmsg_rtc_rdtime(FAR struct rtc_lowerhalf_s *lower, + FAR struct rtc_time *rtctime); +static int rpmsg_rtc_settime(FAR struct rtc_lowerhalf_s *lower, + FAR const struct rtc_time *rtctime); +static bool rpmsg_rtc_havesettime(FAR struct rtc_lowerhalf_s *lower); +#ifdef CONFIG_RTC_ALARM +static int rpmsg_rtc_setalarm(FAR struct rtc_lowerhalf_s *lower_, + FAR const struct lower_setalarm_s *alarminfo); +static int rpmsg_rtc_setrelative(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setrelative_s *relinfo); +static int rpmsg_rtc_cancelalarm(FAR struct rtc_lowerhalf_s *lower, + int alarmid); +static int rpmsg_rtc_rdalarm(FAR struct rtc_lowerhalf_s *lower_, + FAR struct lower_rdalarm_s *alarminfo); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct rtc_ops_s g_rpmsg_rtc_ops = +{ + .rdtime = rpmsg_rtc_rdtime, + .settime = rpmsg_rtc_settime, + .havesettime = rpmsg_rtc_havesettime, +#ifdef CONFIG_RTC_ALARM + .setalarm = rpmsg_rtc_setalarm, + .setrelative = rpmsg_rtc_setrelative, + .cancelalarm = rpmsg_rtc_cancelalarm, + .rdalarm = rpmsg_rtc_rdalarm, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void rpmsg_rtc_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv) +{ + FAR struct rpmsg_rtc_lowerhalf_s *lower = priv; + + if (strcmp(lower->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + lower->ept.priv = lower; + + rpmsg_create_ept(&lower->ept, rdev, RPMSG_RTC_EPT_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + rpmsg_rtc_ept_cb, NULL); + } +} + +static void rpmsg_rtc_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv) +{ + FAR struct rpmsg_rtc_lowerhalf_s *lower = priv; + + if (strcmp(lower->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + rpmsg_destroy_ept(&lower->ept); + } +} + +static void rpmsg_rtc_alarm_fire_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ +#ifdef CONFIG_RTC_ALARM + FAR struct rpmsg_rtc_lowerhalf_s *lower = priv; + FAR struct rpmsg_rtc_alarm_fire_s *msg = data; + FAR struct lower_setalarm_s *alarminfo = &lower->alarminfo[msg->id]; + + alarminfo->cb(alarminfo->priv, alarminfo->id); +#endif +} + +static int rpmsg_rtc_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv) +{ + FAR struct rpmsg_rtc_header_s *header = data; + FAR struct rpmsg_rtc_cookie_s *cookie = + (struct rpmsg_rtc_cookie_s *)(uintptr_t)header->cookie; + + switch (header->command) + { + case RPMSG_RTC_ALARM_FIRE: + rpmsg_rtc_alarm_fire_handler(ept, data, len, src, priv); + break; + + default: + if (cookie) + { + memcpy(cookie->msg, data, len); + nxsem_post(&cookie->sem); + } + break; + } + + return 0; +} + +static int rpmsg_rtc_send_recv(FAR struct rpmsg_rtc_lowerhalf_s *lower, + uint32_t command, + FAR struct rpmsg_rtc_header_s *msg, int len) +{ + FAR struct rpmsg_rtc_cookie_s cookie; + int ret; + + nxsem_init(&cookie.sem, 0, 0); + nxsem_setprotocol(&cookie.sem, SEM_PRIO_NONE); + cookie.msg = msg; + + msg->command = command; + msg->result = -ENXIO; + msg->cookie = (uintptr_t)&cookie; + + ret = rpmsg_send(&lower->ept, msg, len); + if (ret < 0) + { + goto fail; + } + + while (1) + { + ret = nxsem_wait(&cookie.sem); + if (ret != -EINTR) + { + if (ret == 0) + { + ret = msg->result; + } + break; + } + } + +fail: + nxsem_destroy(&cookie.sem); + return ret; +} + +static int rpmsg_rtc_rdtime(FAR struct rtc_lowerhalf_s *lower, + FAR struct rtc_time *rtctime) +{ + struct rpmsg_rtc_get_s msg; + int ret; + + ret = rpmsg_rtc_send_recv((FAR struct rpmsg_rtc_lowerhalf_s *)lower, + RPMSG_RTC_GET, (struct rpmsg_rtc_header_s *)&msg, sizeof(msg)); + if (ret >= 0) + { + time_t time = msg.sec; + gmtime_r(&time, (FAR struct tm *)rtctime); + rtctime->tm_nsec = msg.nsec; + } + + return ret; +} + +static int rpmsg_rtc_settime(FAR struct rtc_lowerhalf_s *lower, + FAR const struct rtc_time *rtctime) +{ + struct rpmsg_rtc_set_s msg = + { + .sec = mktime((FAR struct tm *)rtctime), + .nsec = rtctime->tm_nsec, + }; + + return rpmsg_rtc_send_recv((FAR struct rpmsg_rtc_lowerhalf_s *)lower, + RPMSG_RTC_SET, (struct rpmsg_rtc_header_s *)&msg, sizeof(msg)); +} + +static bool rpmsg_rtc_havesettime(FAR struct rtc_lowerhalf_s *lower) +{ + return true; +} + +#ifdef CONFIG_RTC_ALARM +static int rpmsg_rtc_setalarm(FAR struct rtc_lowerhalf_s *lower_, + FAR const struct lower_setalarm_s *alarminfo) +{ + FAR struct rpmsg_rtc_lowerhalf_s *lower = + (FAR struct rpmsg_rtc_lowerhalf_s *)lower_; + struct rpmsg_rtc_alarm_set_s msg = + { + .sec = mktime((FAR struct tm *)&alarminfo->time), + .nsec = alarminfo->time.tm_nsec, + .id = alarminfo->id, + }; + + int ret; + + ret = rpmsg_rtc_send_recv(lower, RPMSG_RTC_ALARM_SET, + (struct rpmsg_rtc_header_s *)&msg, sizeof(msg)); + if (ret >= 0) + { + lower->alarminfo[alarminfo->id] = *alarminfo; + } + + return ret; +} + +static int rpmsg_rtc_setrelative(FAR struct rtc_lowerhalf_s *lower, + FAR const struct lower_setrelative_s *relinfo) +{ + struct lower_setalarm_s alarminfo = + { + .id = relinfo->id, + .cb = relinfo->cb, + .priv = relinfo->priv, + }; + + time_t time; + + rpmsg_rtc_rdtime(lower, &alarminfo.time); + time = mktime((FAR struct tm *)&alarminfo.time); + time = time + relinfo->reltime; + gmtime_r(&time, (FAR struct tm *)&alarminfo.time); + + return rpmsg_rtc_setalarm(lower, &alarminfo); +} + +static int rpmsg_rtc_cancelalarm(FAR struct rtc_lowerhalf_s *lower, + int alarmid) +{ + struct rpmsg_rtc_alarm_cancel_s msg = + { + .id = alarmid, + }; + + return rpmsg_rtc_send_recv((FAR struct rpmsg_rtc_lowerhalf_s *)lower, + RPMSG_RTC_ALARM_CANCEL, (struct rpmsg_rtc_header_s *)&msg, + sizeof(msg)); +} + +static int rpmsg_rtc_rdalarm(FAR struct rtc_lowerhalf_s *lower_, + FAR struct lower_rdalarm_s *alarminfo) +{ + FAR struct rpmsg_rtc_lowerhalf_s *lower = + (FAR struct rpmsg_rtc_lowerhalf_s *)lower_; + + *alarminfo->time = lower->alarminfo[alarminfo->id].time; + return 0; +} +#endif + +/**************************************************************************** + * Name: rpmsg_rtc_initialize + * + * Description: + * + * Take remote core RTC as external RTC hardware through rpmsg. + * + * Input Parameters: + * cpuname - current cpu name + * minor - device minor number + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ****************************************************************************/ + +FAR struct rtc_lowerhalf_s *rpmsg_rtc_initialize(FAR const char *cpuname, + int minor) +{ + FAR struct rpmsg_rtc_lowerhalf_s *lower; + + lower = kmm_zalloc(sizeof(*lower)); + if (lower) + { + lower->ops = &g_rpmsg_rtc_ops; + lower->cpuname = cpuname; + + rpmsg_register_callback(lower, + rpmsg_rtc_device_created, + rpmsg_rtc_device_destroy, + NULL); + + rtc_initialize(minor, (FAR struct rtc_lowerhalf_s *)lower); + } + + return (FAR struct rtc_lowerhalf_s *)lower; +} diff --git a/fs/hostfs/Kconfig b/fs/hostfs/Kconfig index 2ab151d590d..736692b729b 100644 --- a/fs/hostfs/Kconfig +++ b/fs/hostfs/Kconfig @@ -21,3 +21,19 @@ config FS_HOSTFS be passed to the 'mount()' routine using the optional 'void *data' parameter. +config FS_HOSTFS_RPMSG + bool "Host File System Rpmsg" + default n + depends on FS_HOSTFS + depends on OPENAMP + ---help--- + Use Host file system to mount directories through rpmsg. + This is the driver that sending the message. + +config FS_HOSTFS_RPMSG_SERVER + bool "Host File System Rpmsg Server" + default n + depends on OPENAMP + ---help--- + Use Host file system to mount directories through rpmsg. + This is the driver that receiving the message. diff --git a/fs/hostfs/Make.defs b/fs/hostfs/Make.defs index 441221d2981..c08dddc9e4f 100644 --- a/fs/hostfs/Make.defs +++ b/fs/hostfs/Make.defs @@ -33,16 +33,24 @@ # ############################################################################ -ifeq ($(CONFIG_FS_HOSTFS),y) - # Files required for HostFS file system support ASRCS += -CSRCS += hostfs.c +CSRCS += # Include HOSTFS build support DEPPATH += --dep-path hostfs VPATH += :hostfs +ifeq ($(CONFIG_FS_HOSTFS),y) +CSRCS += hostfs.c +endif + +ifeq ($(CONFIG_FS_HOSTFS_RPMSG),y) +CSRCS += hostfs_rpmsg.c +endif + +ifeq ($(CONFIG_FS_HOSTFS_RPMSG_SERVER),y) +CSRCS += hostfs_rpmsg_server.c endif diff --git a/fs/hostfs/hostfs_rpmsg.c b/fs/hostfs/hostfs_rpmsg.c new file mode 100644 index 00000000000..b515ba1e394 --- /dev/null +++ b/fs/hostfs/hostfs_rpmsg.c @@ -0,0 +1,749 @@ +/**************************************************************************** + * fs/hostfs/hostfs_rpmsg.c + * Hostfs rpmsg driver + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "hostfs_rpmsg.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct hostfs_rpmsg_s +{ + struct rpmsg_endpoint ept; + FAR const char *cpuname; +}; + +struct hostfs_rpmsg_cookie_s +{ + sem_t sem; + int result; + FAR void *data; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int hostfs_rpmsg_default_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static void hostfs_rpmsg_device_created(struct rpmsg_device *rdev, + FAR void *priv_); +static void hostfs_rpmsg_device_destroy(struct rpmsg_device *rdev, + FAR void *priv_); +static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv); +static int hostfs_rpmsg_send_recv(uint32_t command, bool copy, + FAR struct hostfs_rpmsg_header_s *msg, + int len, FAR void *data); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct hostfs_rpmsg_s g_hostfs_rpmsg; + +static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] = +{ + [HOSTFS_RPMSG_OPEN] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_CLOSE] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_READ] = hostfs_rpmsg_read_handler, + [HOSTFS_RPMSG_WRITE] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_LSEEK] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_IOCTL] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_SYNC] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_DUP] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_FSTAT] = hostfs_rpmsg_stat_handler, + [HOSTFS_RPMSG_FTRUNCATE] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_OPENDIR] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_READDIR] = hostfs_rpmsg_readdir_handler, + [HOSTFS_RPMSG_REWINDDIR] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_CLOSEDIR] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_STATFS] = hostfs_rpmsg_statfs_handler, + [HOSTFS_RPMSG_UNLINK] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_MKDIR] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_default_handler, + [HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int hostfs_rpmsg_default_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_header_s *header = data; + FAR struct hostfs_rpmsg_cookie_s *cookie = + (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; + + cookie->result = header->result; + if (cookie->result >= 0 && cookie->data) + { + memcpy(cookie->data, data, len); + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_header_s *header = data; + FAR struct hostfs_rpmsg_cookie_s *cookie = + (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; + FAR struct hostfs_rpmsg_read_s *rsp = data; + + cookie->result = header->result; + if (cookie->result > 0) + { + memcpy(cookie->data, rsp->buf, B2C(cookie->result)); + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_header_s *header = data; + FAR struct hostfs_rpmsg_cookie_s *cookie = + (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; + FAR struct hostfs_rpmsg_readdir_s *rsp = data; + FAR struct dirent *entry = cookie->data; + + cookie->result = header->result; + if (cookie->result >= 0) + { + nbstr2cstr(entry->d_name, rsp->name, NAME_MAX); + entry->d_name[NAME_MAX] = '\0'; + entry->d_type = rsp->type; + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_header_s *header = data; + FAR struct hostfs_rpmsg_cookie_s *cookie = + (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; + FAR struct hostfs_rpmsg_statfs_s *rsp = data; + FAR struct statfs *buf = cookie->data; + + cookie->result = header->result; + if (cookie->result >= 0) + { + buf->f_type = rsp->buf.f_type; + buf->f_namelen = rsp->buf.f_namelen; + buf->f_bsize = B2C(rsp->buf.f_bsize); + buf->f_blocks = rsp->buf.f_blocks; + buf->f_bfree = rsp->buf.f_bfree; + buf->f_bavail = rsp->buf.f_bavail; + buf->f_files = rsp->buf.f_files; + buf->f_ffree = rsp->buf.f_ffree; + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_header_s *header = data; + FAR struct hostfs_rpmsg_cookie_s *cookie = + (struct hostfs_rpmsg_cookie_s *)(uintptr_t)header->cookie; + FAR struct hostfs_rpmsg_stat_s *rsp = data; + FAR struct stat *buf = cookie->data; + + cookie->result = header->result; + if (cookie->result >= 0) + { + buf->st_mode = rsp->buf.st_mode; + buf->st_size = B2C(rsp->buf.st_size); + buf->st_blksize = B2C(rsp->buf.st_blksize); + buf->st_blocks = rsp->buf.st_blocks; + buf->st_atime = rsp->buf.st_atime; + buf->st_mtime = rsp->buf.st_mtime; + buf->st_ctime = rsp->buf.st_ctime; + } + + nxsem_post(&cookie->sem); + + return 0; +} + +static void hostfs_rpmsg_device_created(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + FAR struct hostfs_rpmsg_s *priv = priv_; + + if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + priv->ept.priv = priv; + rpmsg_create_ept(&priv->ept, rdev, HOSTFS_RPMSG_EPT_NAME, + RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, + hostfs_rpmsg_ept_cb, NULL); + } +} + +static void hostfs_rpmsg_device_destroy(FAR struct rpmsg_device *rdev, + FAR void *priv_) +{ + struct hostfs_rpmsg_s *priv = priv_; + + if (strcmp(priv->cpuname, rpmsg_get_cpuname(rdev)) == 0) + { + rpmsg_destroy_ept(&priv->ept); + } +} + +static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_header_s *header = data; + uint32_t command = header->command; + + if (command < ARRAY_SIZE(g_hostfs_rpmsg_handler)) + { + return g_hostfs_rpmsg_handler[command](ept, data, len, src, priv); + } + + return -EINVAL; +} + +static int hostfs_rpmsg_send_recv(uint32_t command, bool copy, + FAR struct hostfs_rpmsg_header_s *msg, + int len, FAR void *data) +{ + FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + FAR struct hostfs_rpmsg_cookie_s cookie; + int ret; + + memset(&cookie, 0, sizeof(cookie)); + nxsem_init(&cookie.sem, 0, 0); + nxsem_setprotocol(&cookie.sem, SEM_PRIO_NONE); + + if (data) + { + cookie.data = data; + } + else if (copy) + { + cookie.data = msg; + } + + msg->command = command; + msg->result = -ENXIO; + msg->cookie = (uintptr_t)&cookie; + + if (copy) + { + ret = rpmsg_send(&priv->ept, msg, len); + } + else + { + ret = rpmsg_send_nocopy(&priv->ept, msg, len); + } + + if (ret < 0) + { + goto fail; + } + + while (1) + { + ret = nxsem_wait(&cookie.sem); + if (ret != -EINTR) + { + if (ret == 0) + { + ret = cookie.result; + } + + break; + } + } + +fail: + nxsem_destroy(&cookie.sem); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int host_open(FAR const char *pathname, int flags, int mode) +{ + FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + FAR struct hostfs_rpmsg_open_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + msg->flags = flags; + msg->mode = mode; + cstr2bstr(msg->pathname, pathname); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_OPEN, false, + (struct hostfs_rpmsg_header_s *)msg, len, NULL); +} + +int host_close(int fd) +{ + struct hostfs_rpmsg_close_s msg = + { + .fd = fd, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CLOSE, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +ssize_t host_read(int fd, FAR void *buf, size_t count) +{ + size_t read = 0; + int ret = 0; + + while (read < count) + { + struct hostfs_rpmsg_read_s msg = + { + .fd = fd, + .count = C2B(count - read), + }; + + ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_READ, true, + (FAR struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), buf); + if (ret <= 0) + { + break; + } + + read += B2C(ret); + buf += B2C(ret); + } + + return read ? read : ret; +} + +ssize_t host_write(int fd, FAR const void *buf, size_t count) +{ + FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + size_t written = 0; + int ret = 0; + + while (written < count) + { + FAR struct hostfs_rpmsg_write_s *msg; + uint32_t space; + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + ret = -ENOMEM; + break; + } + + space -= sizeof(*msg); + if (space > count - written) + { + space = count - written; + } + + msg->fd = fd; + msg->count = C2B(space); + memcpy(msg->buf, buf + written, space); + + ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_WRITE, false, + (struct hostfs_rpmsg_header_s *)msg, sizeof(*msg) + space, NULL); + if (ret <= 0) + { + break; + } + + written += B2C(ret); + } + + return written ? written : ret; +} + +off_t host_lseek(int fd, off_t offset, int whence) +{ + struct hostfs_rpmsg_lseek_s msg = + { + .fd = fd, + .offset = C2B(offset), + .whence = whence, + }; + + int ret; + + ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_LSEEK, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); + + return ret < 0 ? ret : B2C(ret); +} + +int host_ioctl(int fd, int request, unsigned long arg) +{ + struct hostfs_rpmsg_ioctl_s msg = + { + .fd = fd, + .request = request, + .arg = arg, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_IOCTL, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +void host_sync(int fd) +{ + struct hostfs_rpmsg_sync_s msg = + { + .fd = fd, + }; + + hostfs_rpmsg_send_recv(HOSTFS_RPMSG_SYNC, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +int host_dup(int fd) +{ + struct hostfs_rpmsg_dup_s msg = + { + .fd = fd, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_DUP, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +int host_fstat(int fd, struct stat *buf) +{ + struct hostfs_rpmsg_fstat_s msg = + { + .fd = fd, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FSTAT, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), buf); +} + +int host_ftruncate(int fd, off_t length) +{ + struct hostfs_rpmsg_ftruncate_s msg = + { + .fd = fd, + .length = length, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_FTRUNCATE, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +FAR void *host_opendir(FAR const char *name) +{ + FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + FAR struct hostfs_rpmsg_opendir_s *msg; + uint32_t space; + size_t len; + int ret; + + len = sizeof(*msg); + len += B2C(strlen(name) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return NULL; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, name); + + ret = hostfs_rpmsg_send_recv(HOSTFS_RPMSG_OPENDIR, false, + (struct hostfs_rpmsg_header_s *)msg, len, NULL); + + return ret < 0 ? NULL : (FAR void *)ret; +} + +int host_readdir(FAR void *dirp, FAR struct dirent *entry) +{ + struct hostfs_rpmsg_readdir_s msg = + { + .fd = (uintptr_t)dirp, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_READDIR, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), entry); +} + +void host_rewinddir(FAR void *dirp) +{ + struct hostfs_rpmsg_rewinddir_s msg = + { + .fd = (uintptr_t)dirp, + }; + + hostfs_rpmsg_send_recv(HOSTFS_RPMSG_REWINDDIR, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +int host_closedir(FAR void *dirp) +{ + struct hostfs_rpmsg_closedir_s msg = + { + .fd = (uintptr_t)dirp, + }; + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_CLOSEDIR, true, + (struct hostfs_rpmsg_header_s *)&msg, sizeof(msg), NULL); +} + +int host_statfs(FAR const char *path, FAR struct statfs *buf) +{ + struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + struct hostfs_rpmsg_statfs_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(path) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, path); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_STATFS, false, + (struct hostfs_rpmsg_header_s *)msg, len, buf); +} + +int host_unlink(FAR const char *pathname) +{ + struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + struct hostfs_rpmsg_unlink_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, pathname); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_UNLINK, false, + (struct hostfs_rpmsg_header_s *)msg, len, NULL); +} + +int host_mkdir(FAR const char *pathname, mode_t mode) +{ + struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + struct hostfs_rpmsg_mkdir_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + msg->mode = mode; + cstr2bstr(msg->pathname, pathname); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_MKDIR, false, + (struct hostfs_rpmsg_header_s *)msg, len, NULL); +} + +int host_rmdir(FAR const char *pathname) +{ + struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + struct hostfs_rpmsg_rmdir_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(pathname) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, pathname); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_RMDIR, false, + (struct hostfs_rpmsg_header_s *)msg, len, NULL); +} + +int host_rename(FAR const char *oldpath, FAR const char *newpath) +{ + struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + struct hostfs_rpmsg_rename_s *msg; + size_t len; + size_t oldlen; + uint32_t space; + + len = sizeof(*msg); + oldlen = B2C((strlen(oldpath) + 1 + 0x7) & ~0x7); + len += oldlen + B2C(strlen(newpath) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, oldpath); + cstr2bstr(msg->pathname + oldlen, newpath); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_RENAME, false, + (struct hostfs_rpmsg_header_s *)msg, len, NULL); +} + +int host_stat(FAR const char *path, FAR struct stat *buf) +{ + FAR struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + FAR struct hostfs_rpmsg_stat_s *msg; + uint32_t space; + size_t len; + + len = sizeof(*msg); + len += B2C(strlen(path) + 1); + + msg = rpmsg_get_tx_payload_buffer(&priv->ept, &space, true); + if (!msg) + { + return -ENOMEM; + } + + DEBUGASSERT(len <= space); + + cstr2bstr(msg->pathname, path); + + return hostfs_rpmsg_send_recv(HOSTFS_RPMSG_STAT, false, + (struct hostfs_rpmsg_header_s *)msg, len, buf); +} + +int hostfs_rpmsg_init(FAR const char *cpuname) +{ + struct hostfs_rpmsg_s *priv = &g_hostfs_rpmsg; + + priv->cpuname = cpuname; + + return rpmsg_register_callback(priv, + hostfs_rpmsg_device_created, + hostfs_rpmsg_device_destroy, + NULL); +} diff --git a/fs/hostfs/hostfs_rpmsg.h b/fs/hostfs/hostfs_rpmsg.h new file mode 100644 index 00000000000..85d1c93f541 --- /dev/null +++ b/fs/hostfs/hostfs_rpmsg.h @@ -0,0 +1,201 @@ +/**************************************************************************** + * fs/hostfs/hostfs_rpmsg.h + * Hostfs rpmsg driver header file + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __FS_HOSTFS_HOSTFS_RPMSG_H +#define __FS_HOSTFS_HOSTFS_RPMSG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#define HOSTFS_RPMSG_EPT_NAME "rpmsg-hostfs" + +#define HOSTFS_RPMSG_OPEN 1 +#define HOSTFS_RPMSG_CLOSE 2 +#define HOSTFS_RPMSG_READ 3 +#define HOSTFS_RPMSG_WRITE 4 +#define HOSTFS_RPMSG_LSEEK 5 +#define HOSTFS_RPMSG_IOCTL 6 +#define HOSTFS_RPMSG_SYNC 7 +#define HOSTFS_RPMSG_DUP 8 +#define HOSTFS_RPMSG_FSTAT 9 +#define HOSTFS_RPMSG_FTRUNCATE 10 +#define HOSTFS_RPMSG_OPENDIR 11 +#define HOSTFS_RPMSG_READDIR 12 +#define HOSTFS_RPMSG_REWINDDIR 13 +#define HOSTFS_RPMSG_CLOSEDIR 14 +#define HOSTFS_RPMSG_STATFS 15 +#define HOSTFS_RPMSG_UNLINK 16 +#define HOSTFS_RPMSG_MKDIR 17 +#define HOSTFS_RPMSG_RMDIR 18 +#define HOSTFS_RPMSG_RENAME 19 +#define HOSTFS_RPMSG_STAT 20 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +begin_packed_struct struct hostfs_rpmsg_header_s +{ + uint32_t command; + int32_t result; + uint64_t cookie; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_open_s +{ + struct hostfs_rpmsg_header_s header; + int32_t flags; + int32_t mode; + char pathname[0]; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_close_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_read_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; + uint32_t count; + char buf[0]; +} end_packed_struct; + +#define hostfs_rpmsg_write_s hostfs_rpmsg_read_s + +begin_packed_struct struct hostfs_rpmsg_lseek_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; + int32_t whence; + int32_t offset; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_ioctl_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; + int32_t request; + int32_t arg; +} end_packed_struct; + +#define hostfs_rpmsg_sync_s hostfs_rpmsg_close_s +#define hostfs_rpmsg_dup_s hostfs_rpmsg_close_s + +begin_packed_struct struct hostfs_rpmsg_fstat_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; + uint32_t reserved; + struct stat buf; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_ftruncate_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; + int32_t length; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_opendir_s +{ + struct hostfs_rpmsg_header_s header; + char pathname[0]; +} end_packed_struct; + +begin_packed_struct struct hostfs_rpmsg_readdir_s +{ + struct hostfs_rpmsg_header_s header; + int32_t fd; + uint32_t type; + char name[0]; +} end_packed_struct; + +#define hostfs_rpmsg_rewinddir_s hostfs_rpmsg_close_s +#define hostfs_rpmsg_closedir_s hostfs_rpmsg_close_s + +begin_packed_struct struct hostfs_rpmsg_statfs_s +{ + struct hostfs_rpmsg_header_s header; + union + { + struct statfs buf; + uint32_t reserved[16]; + }; + + char pathname[0]; +} end_packed_struct; + +#define hostfs_rpmsg_unlink_s hostfs_rpmsg_opendir_s + +begin_packed_struct struct hostfs_rpmsg_mkdir_s +{ + struct hostfs_rpmsg_header_s header; + int32_t mode; + uint32_t reserved; + char pathname[0]; +} end_packed_struct; + +#define hostfs_rpmsg_rmdir_s hostfs_rpmsg_opendir_s +#define hostfs_rpmsg_rename_s hostfs_rpmsg_opendir_s + +begin_packed_struct struct hostfs_rpmsg_stat_s +{ + struct hostfs_rpmsg_header_s header; + union + { + struct stat buf; + uint32_t reserved[16]; + }; + + char pathname[0]; +} end_packed_struct; + +#endif /* __FS_HOSTFS_HOSTFS_RPMSG_H */ diff --git a/fs/hostfs/hostfs_rpmsg_server.c b/fs/hostfs/hostfs_rpmsg_server.c new file mode 100644 index 00000000000..dac6caf9c4b --- /dev/null +++ b/fs/hostfs/hostfs_rpmsg_server.c @@ -0,0 +1,646 @@ +/**************************************************************************** + * fs/hostfs/hostfs_rpmsg_server.c + * Hostfs rpmsg driver on server + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "hostfs_rpmsg.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct hostfs_rpmsg_server_s +{ + struct rpmsg_endpoint ept; + struct file files[CONFIG_NFILE_DESCRIPTORS]; + void *dirs[CONFIG_NFILE_DESCRIPTORS]; + sem_t sem; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_); +static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_unlink_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_mkdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_rmdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); + +static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, + FAR void *priv_, FAR const char *name, + uint32_t dest); +static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept); +static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, uint32_t src, + FAR void *priv); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const rpmsg_ept_cb g_hostfs_rpmsg_handler[] = +{ + [HOSTFS_RPMSG_OPEN] = hostfs_rpmsg_open_handler, + [HOSTFS_RPMSG_CLOSE] = hostfs_rpmsg_close_handler, + [HOSTFS_RPMSG_READ] = hostfs_rpmsg_read_handler, + [HOSTFS_RPMSG_WRITE] = hostfs_rpmsg_write_handler, + [HOSTFS_RPMSG_LSEEK] = hostfs_rpmsg_lseek_handler, + [HOSTFS_RPMSG_IOCTL] = hostfs_rpmsg_ioctl_handler, + [HOSTFS_RPMSG_SYNC] = hostfs_rpmsg_sync_handler, + [HOSTFS_RPMSG_DUP] = hostfs_rpmsg_dup_handler, + [HOSTFS_RPMSG_FSTAT] = hostfs_rpmsg_fstat_handler, + [HOSTFS_RPMSG_FTRUNCATE] = hostfs_rpmsg_ftruncate_handler, + [HOSTFS_RPMSG_OPENDIR] = hostfs_rpmsg_opendir_handler, + [HOSTFS_RPMSG_READDIR] = hostfs_rpmsg_readdir_handler, + [HOSTFS_RPMSG_REWINDDIR] = hostfs_rpmsg_rewinddir_handler, + [HOSTFS_RPMSG_CLOSEDIR] = hostfs_rpmsg_closedir_handler, + [HOSTFS_RPMSG_STATFS] = hostfs_rpmsg_statfs_handler, + [HOSTFS_RPMSG_UNLINK] = hostfs_rpmsg_unlink_handler, + [HOSTFS_RPMSG_MKDIR] = hostfs_rpmsg_mkdir_handler, + [HOSTFS_RPMSG_RMDIR] = hostfs_rpmsg_rmdir_handler, + [HOSTFS_RPMSG_RENAME] = hostfs_rpmsg_rename_handler, + [HOSTFS_RPMSG_STAT] = hostfs_rpmsg_stat_handler, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int hostfs_rpmsg_open_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_open_s *msg = data; + int i; + int ret = -ENOENT; + + nxsem_wait(&priv->sem); + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + if (!priv->files[i].f_inode) + { + ret = file_open(&priv->files[i], msg->pathname, msg->flags, + msg->mode); + if (ret >= 0) + { + ret = i; + } + + break; + } + } + + nxsem_post(&priv->sem); + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_close_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_close_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + nxsem_wait(&priv->sem); + ret = file_close(&priv->files[msg->fd]); + nxsem_post(&priv->sem); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_read_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_read_s *msg = data; + FAR struct hostfs_rpmsg_read_s *rsp; + int ret = -ENOENT; + uint32_t space; + + rsp = rpmsg_get_tx_payload_buffer(ept, &space, true); + if (!rsp) + { + return -ENOMEM; + } + + *rsp = *msg; + + space -= sizeof(*msg); + if (space > msg->count) + { + space = msg->count; + } + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_read(&priv->files[msg->fd], rsp->buf, space); + } + + rsp->header.result = ret; + return rpmsg_send_nocopy(ept, rsp, (ret < 0 ? 0 : ret) + sizeof(*rsp)); +} + +static int hostfs_rpmsg_write_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_write_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_write(&priv->files[msg->fd], msg->buf, msg->count); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_lseek_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_lseek_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_seek(&priv->files[msg->fd], msg->offset, msg->whence); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_ioctl_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_ioctl(&priv->files[msg->fd], msg->request, msg->arg); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_sync_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_sync_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_fsync(&priv->files[msg->fd]); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_dup_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_dup_s *msg = data; + int i; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + nxsem_wait(&priv->sem); + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + if (!priv->files[i].f_inode) + { + ret = file_dup2(&priv->files[msg->fd], &priv->files[i]); + if (ret >= 0) + { + ret = i; + } + + break; + } + } + + nxsem_post(&priv->sem); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_fstat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_fstat_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_fstat(&priv->files[msg->fd], &msg->buf); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_ftruncate_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_ftruncate_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 0 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = file_truncate(&priv->files[msg->fd], msg->length); + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_opendir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_opendir_s *msg = data; + FAR void *dir; + int i; + int ret = -ENOENT; + + dir = opendir(msg->pathname); + if (dir) + { + nxsem_wait(&priv->sem); + for (i = 1; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + if (!priv->dirs[i]) + { + priv->dirs[i] = dir; + ret = i; + break; + } + } + + nxsem_post(&priv->sem); + + if (ret < 0) + { + closedir(dir); + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_readdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_readdir_s *msg = data; + FAR struct dirent *entry; + int ret = -ENOENT; + + if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + entry = readdir(priv->dirs[msg->fd]); + if (entry) + { + msg->type = entry->d_type; + strcpy(msg->name, entry->d_name); + len += strlen(entry->d_name) + 1; + ret = 0; + } + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, len); +} + +static int hostfs_rpmsg_rewinddir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_rewinddir_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + rewinddir(priv->dirs[msg->fd]); + ret = 0; + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_closedir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct hostfs_rpmsg_server_s *priv = priv_; + FAR struct hostfs_rpmsg_closedir_s *msg = data; + int ret = -ENOENT; + + if (msg->fd >= 1 && msg->fd < CONFIG_NFILE_DESCRIPTORS) + { + ret = closedir(priv->dirs[msg->fd]); + nxsem_wait(&priv->sem); + priv->dirs[msg->fd] = NULL; + nxsem_post(&priv->sem); + ret = ret ? get_errno(ret) : 0; + } + + msg->header.result = ret; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_statfs_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_statfs_s *msg = data; + int ret; + + ret = statfs(msg->pathname, &msg->buf); + msg->header.result = ret ? get_errno(ret) : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_unlink_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_unlink_s *msg = data; + int ret; + + ret = unlink(msg->pathname); + msg->header.result = ret ? get_errno(ret) : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_mkdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_mkdir_s *msg = data; + int ret; + + ret = mkdir(msg->pathname, msg->mode); + msg->header.result = ret ? get_errno(ret) : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_rmdir_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_rmdir_s *msg = data; + int ret; + + ret = rmdir(msg->pathname); + msg->header.result = ret ? get_errno(ret) : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_rename_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_rename_s *msg = data; + FAR char *newpath; + size_t oldlen; + int ret; + + oldlen = (strlen(msg->pathname) + 1 + 0x7) & ~0x7; + newpath = msg->pathname + oldlen; + + ret = rename(msg->pathname, newpath); + msg->header.result = ret ? get_errno(ret) : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static int hostfs_rpmsg_stat_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv) +{ + FAR struct hostfs_rpmsg_stat_s *msg = data; + int ret; + + ret = stat(msg->pathname, &msg->buf); + msg->header.result = ret ? get_errno(ret) : 0; + return rpmsg_send(ept, msg, sizeof(*msg)); +} + +static void hostfs_rpmsg_ns_bind(FAR struct rpmsg_device *rdev, + FAR void *priv_, FAR const char *name, + uint32_t dest) +{ + FAR struct hostfs_rpmsg_server_s *priv; + int ret; + + if (strcmp(name, HOSTFS_RPMSG_EPT_NAME)) + { + return; + } + + priv = kmm_zalloc(sizeof(*priv)); + if (!priv) + { + return; + } + + priv->ept.priv = priv; + nxsem_init(&priv->sem, 0, 1); + + ret = rpmsg_create_ept(&priv->ept, rdev, HOSTFS_RPMSG_EPT_NAME, + RPMSG_ADDR_ANY, dest, + hostfs_rpmsg_ept_cb, hostfs_rpmsg_ns_unbind); + if (ret) + { + nxsem_destroy(&priv->sem); + kmm_free(priv); + } +} + +static void hostfs_rpmsg_ns_unbind(FAR struct rpmsg_endpoint *ept) +{ + FAR struct hostfs_rpmsg_server_s *priv = ept->priv; + int i; + + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + if (priv->files[i].f_inode) + { + file_close(&priv->files[i]); + } + } + + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + if (priv->dirs[i]) + { + closedir(priv->dirs[i]); + } + } + + rpmsg_destroy_ept(&priv->ept); + nxsem_destroy(&priv->sem); + + kmm_free(priv); +} + +static int hostfs_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept, FAR void *data, + size_t len, uint32_t src, FAR void *priv) +{ + struct hostfs_rpmsg_header_s *header = data; + uint32_t command = header->command; + + if (command < ARRAY_SIZE(g_hostfs_rpmsg_handler)) + { + return g_hostfs_rpmsg_handler[command](ept, data, len, src, priv); + } + + return -EINVAL; +} + +int hostfs_rpmsg_server_init(void) +{ + return rpmsg_register_callback(NULL, + NULL, + NULL, + hostfs_rpmsg_ns_bind); +} diff --git a/include/.gitignore b/include/.gitignore index bb0a48a3be0..f4938fd67d7 100644 --- a/include/.gitignore +++ b/include/.gitignore @@ -9,3 +9,6 @@ /uClibc++ /libcxx /machine +/openamp +/metal + diff --git a/include/nuttx/b2c.h b/include/nuttx/b2c.h new file mode 100644 index 00000000000..632c6844e04 --- /dev/null +++ b/include/nuttx/b2c.h @@ -0,0 +1,124 @@ +/**************************************************************************** + * include/nuttx/b2c.h + * + * Copyright (C) 2019 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_B2C_H +#define __INCLUDE_NUTTX_B2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if CHAR_BIT == 8 +# define CHAR_BYTE 1 +# define CHAR_SHIFT 0 +#elif CHAR_BIT == 16 +# define CHAR_BYTE 2 +# define CHAR_SHIFT 1 +#elif CHAR_BIT == 32 +# define CHAR_BYTE 4 +# define CHAR_SHIFT 2 +#else +# error unsupport CHAR_BIT value +#endif + +/* Macros convert between chars and bytes */ + +#define B2C(x) (((x) + CHAR_BYTE - 1) >> CHAR_SHIFT) +#define C2B(x) ((x) << CHAR_SHIFT) + +#define B2C_OFF(x) ((x) >> CHAR_SHIFT) +#define C2B_OFF(x) ((x) << CHAR_SHIFT) + +#define B2C_REM(x) ((x) - C2B_OFF(B2C_OFF(x))) + +#define B2C_SHIFT(x) ((x) - CHAR_SHIFT) +#define C2B_SHIFT(x) ((x) + CHAR_SHIFT) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Functions convert between chars and bytes */ + +#if CHAR_BIT != 8 + +size_t bstrnlen(FAR const char *src, size_t maxlen); + +FAR char *ancstr2bstr(FAR const char *src, size_t maxlen); +FAR char *anbstr2cstr(FAR const char *src, size_t maxlen); + +void ncstr2bstr(FAR char *dst, FAR const char *src, size_t maxlen); +void nbstr2cstr(FAR char *dst, FAR const char *src, size_t maxlen); + +void cmem2bmem(FAR void *dst, size_t rem, FAR const void *src, size_t len); +void bmem2cmem(FAR void *dst, FAR const void *src, size_t rem, size_t len); + +# define cstr2bstr(dst, src) ncstr2bstr(dst, src, SIZE_MAX) +# define bstr2cstr(dst, src) nbstr2cstr(dst, src, SIZE_MAX) + +#else + +# define bstrnlen(src, maxlen) strnlen(src, maxlen) + +# define ancstr2bstr(src, maxlen) strndup(src, maxlen) +# define anbstr2cstr(src, maxlen) strndup(src, maxlen) + +# define ncstr2bstr(dst, src, maxlen) strncpy(dst, src, maxlen) +# define nbstr2cstr(dst, src, maxlen) strncpy(dst, src, maxlen) + +# define cmem2bmem(dst, rem, src, len) memcpy((FAR char *)(dst) + rem, src, len) +# define bmem2cmem(dst, src, rem, len) memcpy(dst, (FAR char *)(src) + rem, len) + +# define cstr2bstr(dst, src) strcpy(dst, src) +# define bstr2cstr(dst, src) strcpy(dst, src) + +#endif + +#define bstrlen(src) bstrnlen(src, SIZE_MAX) + +#define acstr2bstr(src) ancstr2bstr(src, SIZE_MAX) +#define abstr2cstr(src) anbstr2cstr(src, SIZE_MAX) + +#endif /* __INCLUDE_NUTTX_B2C_H */ diff --git a/include/nuttx/fs/hostfs_rpmsg.h b/include/nuttx/fs/hostfs_rpmsg.h new file mode 100644 index 00000000000..c34803cee91 --- /dev/null +++ b/include/nuttx/fs/hostfs_rpmsg.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * include/nuttx/fs/hostfs_rpmsg.h + * Hostfs rpmsg driver header file + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_FS_HOSTFS_H +#define __INCLUDE_NUTTX_FS_HOSTFS_H + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_FS_HOSTFS_RPMSG +int hostfs_rpmsg_init(FAR const char *cpu_name); +#endif + +#ifdef CONFIG_FS_HOSTFS_RPMSG_SERVER +int hostfs_rpmsg_server_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_FS_HOSTFS_H */ diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index 46e8ae89ce7..578fcb02d25 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -96,6 +96,7 @@ #define _FBIOCBASE (0x2800) /* Frame buffer character driver ioctl commands */ #define _NXTERMBASE (0x2900) /* NxTerm character driver ioctl commands */ #define _RFIOCBASE (0x2a00) /* RF devices ioctl commands */ +#define _RPTUNBASE (0x2b00) /* Remote processor tunnel ioctl commands */ /* boardctl() commands share the same number space */ @@ -506,6 +507,11 @@ #define _RFIOCVALID(c) (_IOC_TYPE(c)==_RFIOCBASE) #define _RFIOC(nr) _IOC(_RFIOCBASE,nr) +/* Rptun drivers ************************************************************/ + +#define _RPTUNIOCVALID(c) (_IOC_TYPE(c)==_RPTUNBASE) +#define _RPTUNIOC(nr) _IOC(_RPTUNBASE,nr) + /* boardctl() command definitions *******************************************/ #define _BOARDIOCVALID(c) (_IOC_TYPE(c)==_BOARDBASE) diff --git a/include/nuttx/mbox/mbox.h b/include/nuttx/mbox/mbox.h new file mode 100644 index 00000000000..572a56e1926 --- /dev/null +++ b/include/nuttx/mbox/mbox.h @@ -0,0 +1,146 @@ +/**************************************************************************** + * include/nuttx/mbox/mbox.h + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_MBOX_MBOX_H +#define __INCLUDE_NUTTX_MBOX_MBOX_H + +#ifdef CONFIG_MBOX + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: MBOX_SEND + * + * Description: + * Send a 32bits message to remote core from specific channel + * + * Input Parameters: + * dev - Device-specific state data + * ch - Mbox specific channel + * msg - Message to send + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define MBOX_SEND(d,c,m) ((d)->ops->send(d,c,m)) + +/**************************************************************************** + * Name: MBOX_REGISTER_CALLBACK + * + * Description: + * Attach to receive a callback when something is received on MBOX + * + * Input Parameters: + * dev - Device-specific state data + * ch - Mbox specific channel + * callback - The function to be called when something has been received + * arg - A caller provided value to return with the callback + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define MBOX_REGISTER_CALLBACK(d,c,cb,a) \ + ((d)->ops->registercallback(d,c,cb,a)) + +/**************************************************************************** + * Name: MBOX_UNREGISTER_CALLBACK + * + * Description: + * Detach MBOX callback + * + * Input Parameters: + * dev - Device-specific state data + * ch - Mbox specific channel + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define MBOX_UNREGISTER_CALLBACK(d,c) \ + ((d)->ops->registercallback(d,c,NULL,NULL)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct mbox_dev_s; +typedef CODE int (*mbox_receive_t)(FAR void *arg, uintptr_t msg); + +struct mbox_ops_s +{ + CODE int (*send)(FAR struct mbox_dev_s *dev, uint32_t ch, uintptr_t msg); + CODE int (*registercallback)(FAR struct mbox_dev_s *dev, uint32_t ch, + mbox_receive_t callback, FAR void *arg); +}; + +struct mbox_dev_s +{ + FAR const struct mbox_ops_s *ops; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_MBOX */ +#endif /* __INCLUDE_NUTTX_MBOX_MBOX_H */ diff --git a/include/nuttx/net/rpmsg.h b/include/nuttx/net/rpmsg.h new file mode 100644 index 00000000000..e8e25784c99 --- /dev/null +++ b/include/nuttx/net/rpmsg.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * include/nuttx/net/rpmsg.h + * + * Copyright (C) 2018 Pinecone Inc. All rights reserved. + * Author: Jianli Dong + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_RPMSG_H +#define __INCLUDE_NUTTX_NET_RPMSG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NET_RPMSG_EPT_NAME "rpmsg-%s" + +#define NET_RPMSG_IFUP 0 /* IP-->LINK */ +#define NET_RPMSG_IFDOWN 1 /* IP-->LINK */ +#define NET_RPMSG_ADDMCAST 2 /* IP-->LINK */ +#define NET_RPMSG_RMMCAST 3 /* IP-->LINK */ +#define NET_RPMSG_DEVIOCTL 4 /* IP-->LINK */ +#define NET_RPMSG_SOCKIOCTL 5 /* IP<--LINK */ +#define NET_RPMSG_TRANSFER 6 /* IP<->LINK */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +begin_packed_struct struct net_rpmsg_lnkaddr_s +{ + uint32_t length; + uint8_t addr[16]; +} end_packed_struct; + +begin_packed_struct struct net_rpmsg_header_s +{ + uint32_t command; + int32_t result; + uint64_t cookie; +} end_packed_struct; + +begin_packed_struct struct net_rpmsg_ifup_s +{ + struct net_rpmsg_header_s header; + struct net_rpmsg_lnkaddr_s lnkaddr; + + /* All addresses in the network order */ + + uint32_t ipaddr; + uint32_t draddr; + uint32_t netmask; + uint32_t dnsaddr; + uint16_t ipv6addr[8]; + uint16_t ipv6draddr[8]; + uint16_t ipv6netmask[8]; + uint16_t ipv6dnsaddr[8]; +} end_packed_struct; + +#define net_rpmsg_ifdown_s net_rpmsg_header_s + +begin_packed_struct struct net_rpmsg_mcast_s +{ + struct net_rpmsg_header_s header; + struct net_rpmsg_lnkaddr_s lnkaddr; +} end_packed_struct; + +begin_packed_struct struct net_rpmsg_ioctl_s +{ + struct net_rpmsg_header_s header; + uint32_t code; + uint32_t length; + uint8_t arg[0]; +} end_packed_struct; + +begin_packed_struct struct net_rpmsg_transfer_s +{ + struct net_rpmsg_header_s header; + uint32_t length; + uint8_t data[0]; +} end_packed_struct; + +#endif /* __INCLUDE_NUTTX_NET_RPMSG_H */ diff --git a/include/nuttx/net/rpmsgdrv.h b/include/nuttx/net/rpmsgdrv.h new file mode 100644 index 00000000000..bb38eab53fd --- /dev/null +++ b/include/nuttx/net/rpmsgdrv.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * include/nuttx/net/rpmsgdrv.h + * + * Copyright (C) 2018 Pinecone Inc. All rights reserved. + * Author: Jianli Dong + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_NET_RPMSGDRV_H +#define __INCLUDE_NUTTX_NET_RPMSGDRV_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_NET_RPMSG_DRV +int net_rpmsg_drv_init(FAR const char *cpuname, + FAR const char *devname, + enum net_lltype_e lltype); +#else +#define net_rpmsg_drv_init(cpuname, devname, lltye) +#endif + +#endif /* __INCLUDE_NUTTX_NET_RPMSGDRV_H */ diff --git a/include/nuttx/rptun/openamp.h b/include/nuttx/rptun/openamp.h new file mode 100644 index 00000000000..3e940ee4026 --- /dev/null +++ b/include/nuttx/rptun/openamp.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * include/nuttx/rptun/openamp.h + * + * Copyright (C) 2019 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RPTUN_OPENAMP_H +#define __INCLUDE_NUTTX_RPTUN_OPENAMP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifdef CONFIG_RPTUN + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef void (*rpmsg_dev_cb_t)(FAR struct rpmsg_device *rdev, + FAR void *priv); +typedef void (*rpmsg_bind_cb_t)(FAR struct rpmsg_device *rdev, + FAR void *priv, FAR const char *name, + uint32_t dest); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +const char *rpmsg_get_cpuname(FAR struct rpmsg_device *rdev); +int rpmsg_register_callback(FAR void *priv, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_bind_cb_t ns_bind); +void rpmsg_unregister_callback(FAR void *priv, + rpmsg_dev_cb_t device_created, + rpmsg_dev_cb_t device_destroy, + rpmsg_bind_cb_t ns_bind); + +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_RPTUN */ +#endif /*__INCLUDE_NUTTX_RPTUN_OPENAMP_H */ diff --git a/include/nuttx/rptun/rptun.h b/include/nuttx/rptun/rptun.h new file mode 100644 index 00000000000..0fdd61d95f1 --- /dev/null +++ b/include/nuttx/rptun/rptun.h @@ -0,0 +1,311 @@ +/**************************************************************************** + * include/nuttx/rptun/rptun.h + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_RPTUN_RPTUN_H +#define __INCLUDE_NUTTX_RPTUN_RPTUN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#ifdef CONFIG_RPTUN + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define RPTUNIOC_START _RPTUNIOC(1) +#define RPTUNIOC_STOP _RPTUNIOC(2) + +#define RPTUN_NOTIFY_ALL (UINT32_MAX - 0) + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: RPTUN_GET_CPUNAME + * + * Description: + * Get remote cpu name + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Cpu name on success, NULL on failure. + * + ****************************************************************************/ + +#define RPTUN_GET_CPUNAME(d) ((d)->ops->get_cpuname(d)) + +/**************************************************************************** + * Name: RPTUN_GET_FIRMWARE + * + * Description: + * Get remote firmware name + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Firmware name on success, NULL on failure. + * + ****************************************************************************/ + +#define RPTUN_GET_FIRMWARE(d) ((d)->ops->get_firmware(d)) + +/**************************************************************************** + * Name: RPTUN_GET_ADDRENV + * + * Description: + * Get adress env list + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Addrenv pointer on success, NULL on failure. + * + ****************************************************************************/ + +#define RPTUN_GET_ADDRENV(d) ((d)->ops->get_addrenv(d)) + +/**************************************************************************** + * Name: RPTUN_GET_RESOURCE + * + * Description: + * Get rptun resouce + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Resource pointer on success, NULL on failure + * + ****************************************************************************/ + +#define RPTUN_GET_RESOURCE(d) ((d)->ops->get_resource(d)) + +/**************************************************************************** + * Name: RPTUN_IS_AUTOSTART + * + * Description: + * AUTO start or not + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * True autostart, false not autostart + * + ****************************************************************************/ + +#define RPTUN_IS_AUTOSTART(d) ((d)->ops->is_autostart(d)) + +/**************************************************************************** + * Name: RPTUN_IS_MASTER + * + * Description: + * IS master or not + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * True master, false remote + * + ****************************************************************************/ + +#define RPTUN_IS_MASTER(d) ((d)->ops->is_master(d)) + +/**************************************************************************** + * Name: RPTUN_START + * + * Description: + * START remote cpu + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define RPTUN_START(d) ((d)->ops->start(d)) + +/**************************************************************************** + * Name: RPTUN_STOP + * + * Description: + * STOP remote cpu + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define RPTUN_STOP(d) ((d)->ops->stop(d)) + +/**************************************************************************** + * Name: RPTUN_NOTIFY + * + * Description: + * Notify remote core there is a message to get. + * + * Input Parameters: + * dev - Device-specific state data + * vqid - Message to notify + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define RPTUN_NOTIFY(d,v) ((d)->ops->notify(d,v)) + +/**************************************************************************** + * Name: RPTUN_REGISTER_CALLBACK + * + * Description: + * Attach to receive a callback when something is received on RPTUN + * + * Input Parameters: + * dev - Device-specific state data + * callback - The function to be called when something has been received + * arg - A caller provided value to return with the callback + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define RPTUN_REGISTER_CALLBACK(d,c,a) ((d)->ops->register_callback(d,c,a)) + +/**************************************************************************** + * Name: RPTUN_UNREGISTER_CALLBACK + * + * Description: + * Detach RPTUN callback + * + * Input Parameters: + * dev - Device-specific state data + * + * Returned Value: + * OK unless an error occurs. Then a negated errno value is returned + * + ****************************************************************************/ + +#define RPTUN_UNREGISTER_CALLBACK(d) ((d)->ops->register_callback(d,NULL,NULL)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef CODE int (*rptun_callback_t)(FAR void *arg, uint32_t vqid); + +struct rptun_addrenv_s +{ + uintptr_t pa; + uintptr_t da; + size_t size; +}; + +struct __attribute__((aligned(B2C(8)))) rptun_rsc_s +{ + struct resource_table rsc_tbl_hdr; + unsigned int offset[2]; + struct fw_rsc_trace log_trace; + struct fw_rsc_vdev rpmsg_vdev; + struct fw_rsc_vdev_vring rpmsg_vring0; + struct fw_rsc_vdev_vring rpmsg_vring1; + unsigned int buf_size; +}; + +struct rptun_dev_s; +struct rptun_ops_s +{ + CODE FAR const char *(*get_cpuname)(FAR struct rptun_dev_s *dev); + CODE FAR const char *(*get_firmware)(FAR struct rptun_dev_s *dev); + + CODE FAR const struct rptun_addrenv_s *(*get_addrenv)(FAR struct rptun_dev_s *dev); + CODE FAR struct rptun_rsc_s *(*get_resource)(FAR struct rptun_dev_s *dev); + + CODE bool (*is_autostart)(FAR struct rptun_dev_s *dev); + CODE bool (*is_master)(FAR struct rptun_dev_s *dev); + + CODE int (*start)(FAR struct rptun_dev_s *dev); + CODE int (*stop)(FAR struct rptun_dev_s *dev); + CODE int (*notify)(FAR struct rptun_dev_s *dev, uint32_t vqid); + CODE int (*register_callback)(FAR struct rptun_dev_s *dev, + rptun_callback_t callback, FAR void *arg); +}; + +struct rptun_dev_s +{ + FAR const struct rptun_ops_s *ops; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +int rptun_initialize(FAR struct rptun_dev_s *dev); +int rptun_boot(FAR const char *cpuname); + +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_RPTUN */ +#endif /* __INCLUDE_NUTTX_RPTUN_RPTUN_H */ + diff --git a/include/nuttx/serial/uart_rpmsg.h b/include/nuttx/serial/uart_rpmsg.h new file mode 100644 index 00000000000..b1616158b0a --- /dev/null +++ b/include/nuttx/serial/uart_rpmsg.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * include/nuttx/serial/uart_rpmsg.h + * Serial driver for rpmsg UART + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SERIAL_UART_RPMSG_H +#define __INCLUDE_NUTTX_SERIAL_UART_RPMSG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifdef CONFIG_RPMSG_UART + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +int uart_rpmsg_init(FAR const char *cpu_name, FAR const char *dev_name, + int buf_size, bool isconsole); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_RPMSG_UART */ +#endif /* __INCLUDE_NUTTX_SERIAL_UART_RPMSG_H */ diff --git a/include/nuttx/syslog/syslog_rpmsg.h b/include/nuttx/syslog/syslog_rpmsg.h new file mode 100644 index 00000000000..5d3ef7ed6c9 --- /dev/null +++ b/include/nuttx/syslog/syslog_rpmsg.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * include/nuttx/syslog/syslog_rpmsg.h + * Syslog driver for rpmsg syslog + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SYSLOG_SYSLOG_RPMSG_H +#define __INCLUDE_NUTTX_SYSLOG_SYSLOG_RPMSG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_SYSLOG_RPMSG +int syslog_rpmsg_init_early(FAR const char *cpu_name, FAR void *buffer, + size_t size); +int syslog_rpmsg_init(void); +#endif + +#ifdef CONFIG_SYSLOG_RPMSG_SERVER +int syslog_rpmsg_server_init(void); +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_SYSLOG_SYSLOG_RPMSG_H */ + diff --git a/include/nuttx/timers/rpmsg_rtc.h b/include/nuttx/timers/rpmsg_rtc.h new file mode 100644 index 00000000000..6e12ee9082f --- /dev/null +++ b/include/nuttx/timers/rpmsg_rtc.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * include/nuttx/timers/rpmsg_rtc.h + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Guiding Li + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_TIMERS_RPMSG_RTC_H +#define __INCLUDE_NUTTX_TIMERS_RPMSG_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_RTC_RPMSG + +FAR struct rtc_lowerhalf_s *rpmsg_rtc_initialize(FAR const char *cpu_name, + int minor); + +#endif /* CONFIG_RTC_RPMSG */ + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_TIMERS_RPMSG_RTC_H */ diff --git a/include/string.h b/include/string.h index 0f1ad040c72..46032f2181a 100644 --- a/include/string.h +++ b/include/string.h @@ -44,9 +44,7 @@ #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ +#include /**************************************************************************** * Public Function Prototypes diff --git a/libs/libc/README.txt b/libs/libc/README.txt index d34767f6333..e24daee4f64 100644 --- a/libs/libc/README.txt +++ b/libs/libc/README.txt @@ -50,7 +50,7 @@ we have: semaphore - semaphore.h stdio - stdio.h stdlib - stdlib.h - string - string.h (and legacy strings.h) + string - string.h (and legacy strings.h and non-standard nuttx/b2c.h) time - time.h uio - sys/uio.h unistd - unistd.h diff --git a/libs/libc/string/lib_anbstr2cstr.c b/libs/libc/string/lib_anbstr2cstr.c new file mode 100644 index 00000000000..3cea9213abd --- /dev/null +++ b/libs/libc/string/lib_anbstr2cstr.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * libc/stdlib/lib_anbstr2cstr.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "libc.h" + +#if CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +FAR char *anbstr2cstr(FAR const char *src, size_t maxlen) +{ + FAR char *dst; + size_t len; + + len = bstrnlen(src, maxlen); + dst = lib_malloc(C2B(len + 1)); + if (dst) + { + dst[C2B(len + 1) - 1] = 0; + bmem2cmem(dst, src, 0, len); + } + + return dst; +} + +#endif diff --git a/libs/libc/string/lib_ancstr2bstr.c b/libs/libc/string/lib_ancstr2bstr.c new file mode 100644 index 00000000000..bab32fee267 --- /dev/null +++ b/libs/libc/string/lib_ancstr2bstr.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * libc/stdlib/lib_ancstr2bstr.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "libc.h" + +#if CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +FAR char *ancstr2bstr(FAR const char *src, size_t maxlen) +{ + FAR char *dst; + size_t len; + + len = strnlen(src, maxlen); + dst = lib_malloc(B2C(len + 1)); + if (dst) + { + dst[B2C(len + 1) - 1] = 0; + cmem2bmem(dst, 0, src, len); + } + + return dst; +} + +#endif diff --git a/libs/libc/string/lib_bmem2cmem.c b/libs/libc/string/lib_bmem2cmem.c new file mode 100644 index 00000000000..148383ee67f --- /dev/null +++ b/libs/libc/string/lib_bmem2cmem.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * libc/stdlib/lib_bmem2cmem.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#if !defined(CONFIG_ENDIAN_BIG) && CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void bmem2cmem(FAR void *dst_, FAR const void *src_, size_t rem, size_t len) +{ + char *dst = dst_; + const char *src = src_; + + while (1) + { + int i; + + for (i = 8 * rem; i < CHAR_BIT; i += 8) + { + if (len-- == 0) + { + return; + } + + *dst++ = (*src >> i) & 0xff; + } + + rem = 0; + src++; + } +} + +#endif diff --git a/libs/libc/string/lib_bstrnlen.c b/libs/libc/string/lib_bstrnlen.c new file mode 100644 index 00000000000..af8d7cbf4d5 --- /dev/null +++ b/libs/libc/string/lib_bstrnlen.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * libc/stdlib/lib_bstrnlen.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#if !defined(CONFIG_ENDIAN_BIG) && CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +size_t bstrnlen(FAR const char *src, size_t maxlen) +{ + size_t len = 0; + + while (1) + { + int i; + + for (i = 0; i < CHAR_BIT; i += 8, len++) + { + if (maxlen-- == 0 || ((*src >> i) & 0xff) == 0) + { + return len; + } + } + + src++; + } +} + +#endif diff --git a/libs/libc/string/lib_cmem2bmem.c b/libs/libc/string/lib_cmem2bmem.c new file mode 100644 index 00000000000..e3f45a717a0 --- /dev/null +++ b/libs/libc/string/lib_cmem2bmem.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * libc/stdlib/lib_cmem2bmem.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#if !defined(CONFIG_ENDIAN_BIG) && CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void cmem2bmem(FAR void *dst_, size_t rem, FAR const void *src_, size_t len) +{ + char *dst = dst_; + const char *src = src_; + + while (1) + { + int i; + + for (i = 8 * rem; i < CHAR_BIT; i += 8) + { + if (len-- == 0) + { + return; + } + else if (i == 8 * rem) + { + *dst = 0; + } + + *dst |= (*src++ & 0xff) << i; + } + + rem = 0; + dst++; + } +} + +#endif diff --git a/libs/libc/string/lib_nbstr2cstr.c b/libs/libc/string/lib_nbstr2cstr.c new file mode 100644 index 00000000000..4edd30fbea1 --- /dev/null +++ b/libs/libc/string/lib_nbstr2cstr.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * libc/stdlib/lib_nbstr2cstr.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#if !defined(CONFIG_ENDIAN_BIG) && CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void nbstr2cstr(FAR char *dst, FAR const char *src, size_t maxlen) +{ + while (1) + { + int i; + + for (i = 0; i < CHAR_BIT; i += 8) + { + if (maxlen-- == 0) + { + return; + } + + *dst = (*src >> i) & 0xff; + if (*dst++ == 0) + { + return; + } + } + + src++; + } +} + +#endif diff --git a/libs/libc/string/lib_ncstr2bstr.c b/libs/libc/string/lib_ncstr2bstr.c new file mode 100644 index 00000000000..ef6bb754fa2 --- /dev/null +++ b/libs/libc/string/lib_ncstr2bstr.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * libc/stdlib/lib_ncstr2bstr.c + * + * Copyright (C) 2017 Pinecone Inc. All rights reserved. + * Author: Xiang Xiao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#if !defined(CONFIG_ENDIAN_BIG) && CHAR_BIT != 8 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void ncstr2bstr(FAR char *dst, FAR const char *src, size_t maxlen) +{ + while (1) + { + int i; + + for (i = 0; i < CHAR_BIT; i += 8) + { + char tmp; + + if (maxlen-- == 0) + { + return; + } + else if (i == 0) + { + *dst = 0; + } + + tmp = *src++ & 0xff; + if (tmp == 0) + { + return; + } + + *dst |= tmp << i; + } + + dst++; + } +} + +#endif diff --git a/openamp/.gitignore b/openamp/.gitignore new file mode 100644 index 00000000000..95c5cfa3992 --- /dev/null +++ b/openamp/.gitignore @@ -0,0 +1,4 @@ +/.libmetal_headers +/.openamp_headers +/libmetal +/open-amp diff --git a/openamp/Kconfig b/openamp/Kconfig new file mode 100644 index 00000000000..f8bbd62de7d --- /dev/null +++ b/openamp/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config OPENAMP + bool "Open Asymmetric Multi Processing support" + default n + ---help--- + Enable or disable Open Asymmetric Multi Processing features + +if OPENAMP + +endif # OPENAMP diff --git a/openamp/Makefile b/openamp/Makefile new file mode 100644 index 00000000000..f6aa98382e2 --- /dev/null +++ b/openamp/Makefile @@ -0,0 +1,84 @@ +############################################################################ +# openamp/Makefile +# +# Copyright (C) 2017 Pinecone Inc. All rights reserved. +# Author: Pinecone +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = + +VPATH := $(SRCDIR) +DEPPATH = --dep-path . + +include libmetal/Make.defs +include open-amp/Make.defs + +AOBJS = $(ASRCS:.S=$(OBJEXT)) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libopenamp$(LIBEXT) + +all: $(BIN) +.PHONY: context depend clean distclean dirlinks + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN): $(OBJS) + $(call ARCHIVE, $@, $(OBJS)) + +dirlinks:: + +.depend: Makefile $(SRCS) + $(Q) $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $^ >Make.dep + $(Q) touch $@ + +depend: .depend + +clean: + $(foreach obj,$(OBJS),$(call DELFILE, $(obj))) + $(call DELFILE, $(BIN)) + $(call CLEAN) + +distclean:: clean + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep diff --git a/tools/Directories.mk b/tools/Directories.mk index bed2972795c..ab12a3f5611 100644 --- a/tools/Directories.mk +++ b/tools/Directories.mk @@ -166,4 +166,10 @@ else CLEANDIRS += crypto endif +ifeq ($(CONFIG_OPENAMP),y) +KERNDEPDIRS += openamp +else +CLEANDIRS += openamp +endif + CLEANDIRS += $(KERNDEPDIRS) $(USERDEPDIRS) diff --git a/tools/FlatLibs.mk b/tools/FlatLibs.mk index 61e16e6a065..988bdd66350 100644 --- a/tools/FlatLibs.mk +++ b/tools/FlatLibs.mk @@ -132,6 +132,10 @@ ifeq ($(CONFIG_LIBDSP),y) NUTTXLIBS += staging$(DELIM)libdsp$(LIBEXT) endif +ifeq ($(CONFIG_OPENAMP),y) +NUTTXLIBS += staging$(DELIM)libopenamp$(LIBEXT) +endif + # Export all libraries EXPORTLIBS = $(NUTTXLIBS) diff --git a/tools/KernelLibs.mk b/tools/KernelLibs.mk index 5922180beed..575c97ca3f0 100644 --- a/tools/KernelLibs.mk +++ b/tools/KernelLibs.mk @@ -117,6 +117,10 @@ ifeq ($(CONFIG_LIBDSP),y) NUTTXLIBS += staging$(DELIM)libdsp$(LIBEXT) endif +ifeq ($(CONFIG_OPENAMP),y) +NUTTXLIBS += staging$(DELIM)libopenamp$(LIBEXT) +endif + # Export only the user libraries EXPORTLIBS = $(USERLIBS) diff --git a/tools/LibTargets.mk b/tools/LibTargets.mk index d71cdaf8781..65f2976ef49 100644 --- a/tools/LibTargets.mk +++ b/tools/LibTargets.mk @@ -148,6 +148,12 @@ libs$(DELIM)libdsp$(DELIM)libdsp$(LIBEXT): context staging$(DELIM)libdsp$(LIBEXT): libs$(DELIM)libdsp$(DELIM)libdsp$(LIBEXT) $(Q) $(call INSTALL_LIB,$<,$@) +openamp$(DELIM)libopenamp$(LIBEXT): context + $(Q) $(MAKE) -C openamp TOPDIR="$(TOPDIR)" libopenamp$(LIBEXT) KERNEL=y EXTRADEFINES=$(KDEFINE) + +staging$(DELIM)libopenamp$(LIBEXT): openamp$(DELIM)libopenamp$(LIBEXT) + $(Q) $(call INSTALL_LIB,$<,$@) + # Special case syscall$(DELIM)libstubs$(LIBEXT): context diff --git a/tools/Makefile.unix b/tools/Makefile.unix index 5550357a78e..7107578894f 100644 --- a/tools/Makefile.unix +++ b/tools/Makefile.unix @@ -372,6 +372,7 @@ endif dirlinks: include/arch include/arch/board include/arch/chip $(ARCH_SRC)/board $(ARCH_SRC)/chip $(ARCH_SRC)/drivers $(Q) $(MAKE) -C boards dirlinks TOPDIR="$(TOPDIR)" + $(Q) $(MAKE) -C openamp dirlinks TOPDIR="$(TOPDIR)" $(Q) $(MAKE) -C $(CONFIG_APPS_DIR) dirlinks TOPDIR="$(TOPDIR)" # context diff --git a/tools/Makefile.win b/tools/Makefile.win index 7e6b974f9f9..a40ab7cb20a 100644 --- a/tools/Makefile.win +++ b/tools/Makefile.win @@ -388,6 +388,7 @@ endif dirlinks: include\arch include\arch\board include\arch\chip $(ARCH_SRC)\board $(ARCH_SRC)\chip $(ARCH_SRC)\drivers $(Q) $(MAKE) -C boards dirlinks TOPDIR="$(TOPDIR)" + $(Q) $(MAKE) -C openamp dirlinks TOPDIR="$(TOPDIR)" $(Q) $(MAKE) -C $(CONFIG_APPS_DIR) dirlinks TOPDIR="$(TOPDIR)" # context diff --git a/tools/ProtectedLibs.mk b/tools/ProtectedLibs.mk index c7b7d9865ed..3a1a75a9aac 100644 --- a/tools/ProtectedLibs.mk +++ b/tools/ProtectedLibs.mk @@ -132,6 +132,10 @@ ifeq ($(CONFIG_LIBDSP),y) NUTTXLIBS += staging$(DELIM)libdsp$(LIBEXT) endif +ifeq ($(CONFIG_OPENAMP),y) +NUTTXLIBS += staging$(DELIM)libopenamp$(LIBEXT) +endif + # Export only the user libraries EXPORTLIBS = $(USERLIBS)