You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/03/07 09:46:03 UTC

[incubator-nuttx] branch master updated (cb9ff5f -> 70442d1)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from cb9ff5f  tools/version.h: If the version is not available, use 0.0.0
     new 64708dd  drivers/serial/Kconfig: fix configure warnning
     new 24cc83e  serial/serial_dma.c: fix warnnings
     new 70442d1  net/socket_rpmsg: add net socket rpmsg support

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 boards/sim/sim/sim/configs/rpproxy/defconfig    |    3 +
 boards/sim/sim/sim/configs/rpserver/defconfig   |    5 +
 drivers/serial/Kconfig                          |    2 -
 drivers/serial/serial_dma.c                     |    2 +-
 fs/mqueue/mqueue.h => include/netpacket/rpmsg.h |   30 +-
 include/sys/socket.h                            |    2 +
 net/Kconfig                                     |    1 +
 net/Makefile                                    |    1 +
 net/rpmsg/Kconfig                               |   32 +
 {libs/libc/lzf => net/rpmsg}/Make.defs          |   16 +-
 include/libgen.h => net/rpmsg/rpmsg.h           |   23 +-
 net/rpmsg/rpmsg_sockif.c                        | 1192 +++++++++++++++++++++++
 net/socket/net_sockif.c                         |    7 +
 net/socket/socket.c                             |    2 +-
 14 files changed, 1280 insertions(+), 38 deletions(-)
 copy fs/mqueue/mqueue.h => include/netpacket/rpmsg.h (76%)
 create mode 100644 net/rpmsg/Kconfig
 copy {libs/libc/lzf => net/rpmsg}/Make.defs (80%)
 copy include/libgen.h => net/rpmsg/rpmsg.h (80%)
 create mode 100644 net/rpmsg/rpmsg_sockif.c


[incubator-nuttx] 02/03: serial/serial_dma.c: fix warnnings

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 24cc83e46fce67af8fad7338e444850b4f4b13e6
Author: ligd <li...@xiaomi.com>
AuthorDate: Fri Mar 5 22:30:03 2021 +0800

    serial/serial_dma.c: fix warnnings
    
    serial/serial_dma.c: In function ‘uart_recvchars_done’:
    serial/serial_dma.c:407:7: warning: implicit declaration of function ‘nxsig_kill’ [-Wimplicit-function-declaration]
      407 |       nxsig_kill(dev->pid, signo);
          |       ^~~~~~~~~~
    
    Change-Id: I9e1c0341ecce3033889d11fff9ec2b9e3dfe303b
---
 drivers/serial/serial_dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/serial/serial_dma.c b/drivers/serial/serial_dma.c
index 2a4c738..81cc7ff 100644
--- a/drivers/serial/serial_dma.c
+++ b/drivers/serial/serial_dma.c
@@ -42,7 +42,7 @@
 #include <sys/types.h>
 #include <stdint.h>
 #include <debug.h>
-#include <signal.h>
+#include <nuttx/signal.h>
 
 #include <nuttx/serial/serial.h>
 


[incubator-nuttx] 01/03: drivers/serial/Kconfig: fix configure warnning

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 64708ddc7a3ca25fd1bf29e30ace3238c9f93e2d
Author: ligd <li...@xiaomi.com>
AuthorDate: Fri Mar 5 22:29:18 2021 +0800

    drivers/serial/Kconfig: fix configure warnning
    
    user should select the default action by self:
    warning: (TTY_SIGINT) selects SIG_SIGKILL_ACTION which has unmet direct dependencies (SIG_DEFAULT)
    
    Change-Id: Ied9899d18156742ce4998b40d53a481262dcd84a
    Signed-off-by: ligd <li...@xiaomi.com>
---
 drivers/serial/Kconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 22e6b14..2dd39d7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -177,7 +177,6 @@ config SERIAL_TERMIOS
 config TTY_SIGINT
 	bool "Support SIGINT"
 	default n
-	select SIG_SIGKILL_ACTION
 	depends on SERIAL_TERMIOS
 	---help---
 		Whether support Ctrl-c/x event.  Enabled automatically for console
@@ -222,7 +221,6 @@ config TTY_SIGINT_CHAR
 config TTY_SIGTSTP
 	bool "Support SIGTSTP"
 	default n
-	select CONFIG_SIG_SIGSTOP_ACTION
 	depends on SERIAL_TERMIOS
 	---help---
 		Whether support Ctrl-z event.  Enabled automatically for console


[incubator-nuttx] 03/03: net/socket_rpmsg: add net socket rpmsg support

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 70442d1f9d1bb56926f64f2edb81650cb464d798
Author: ligd <li...@xiaomi.com>
AuthorDate: Thu Nov 5 20:30:49 2020 +0800

    net/socket_rpmsg: add net socket rpmsg support
    
    Change-Id: Ie23ee4c0052cf2fc66972ea9bc5f11c070fbcf8a
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 boards/sim/sim/sim/configs/rpproxy/defconfig  |    3 +
 boards/sim/sim/sim/configs/rpserver/defconfig |    5 +
 include/netpacket/rpmsg.h                     |   42 +
 include/sys/socket.h                          |    2 +
 net/Kconfig                                   |    1 +
 net/Makefile                                  |    1 +
 net/rpmsg/Kconfig                             |   32 +
 net/rpmsg/Make.defs                           |   32 +
 net/rpmsg/rpmsg.h                             |   53 ++
 net/rpmsg/rpmsg_sockif.c                      | 1192 +++++++++++++++++++++++++
 net/socket/net_sockif.c                       |    7 +
 net/socket/socket.c                           |    2 +-
 12 files changed, 1371 insertions(+), 1 deletion(-)

diff --git a/boards/sim/sim/sim/configs/rpproxy/defconfig b/boards/sim/sim/sim/configs/rpproxy/defconfig
index d780f6f..d8b7b35 100644
--- a/boards/sim/sim/sim/configs/rpproxy/defconfig
+++ b/boards/sim/sim/sim/configs/rpproxy/defconfig
@@ -13,7 +13,9 @@ CONFIG_ARCH_CHIP="sim"
 CONFIG_ARCH_SIM=y
 CONFIG_BOARDCTL_POWEROFF=y
 CONFIG_BUILTIN=y
+CONFIG_DEBUG_SYMBOLS=y
 CONFIG_DEV_SIMPLE_ADDRENV=y
+CONFIG_EXAMPLES_RPMSGSOCKET=y
 CONFIG_FS_HOSTFS=y
 CONFIG_FS_HOSTFS_RPMSG=y
 CONFIG_FS_PROCFS=y
@@ -26,6 +28,7 @@ CONFIG_NETDB_DNSCLIENT_RECV_TIMEOUT=3
 CONFIG_NETDB_DNSSERVER_IPv4ADDR=0x771d1d1d
 CONFIG_NETUTILS_USRSOCK_RPMSG=y
 CONFIG_NET_ICMP_NO_STACK=y
+CONFIG_NET_RPMSG=y
 CONFIG_NET_SOCKOPTS=y
 CONFIG_NET_TCP_NO_STACK=y
 CONFIG_NET_UDP_NO_STACK=y
diff --git a/boards/sim/sim/sim/configs/rpserver/defconfig b/boards/sim/sim/sim/configs/rpserver/defconfig
index f4f2d5d..cce43dd 100644
--- a/boards/sim/sim/sim/configs/rpserver/defconfig
+++ b/boards/sim/sim/sim/configs/rpserver/defconfig
@@ -12,7 +12,9 @@ CONFIG_ARCH_CHIP="sim"
 CONFIG_ARCH_SIM=y
 CONFIG_BOARDCTL_POWEROFF=y
 CONFIG_BUILTIN=y
+CONFIG_DEBUG_SYMBOLS=y
 CONFIG_DEV_SIMPLE_ADDRENV=y
+CONFIG_EXAMPLES_RPMSGSOCKET=y
 CONFIG_FS_HOSTFS=y
 CONFIG_FS_HOSTFS_RPMSG_SERVER=y
 CONFIG_FS_PROCFS=y
@@ -34,6 +36,7 @@ CONFIG_NET_BROADCAST=y
 CONFIG_NET_ICMP=y
 CONFIG_NET_ICMP_SOCKET=y
 CONFIG_NET_LOOPBACK=y
+CONFIG_NET_RPMSG=y
 CONFIG_NET_SOCKOPTS=y
 CONFIG_NET_STATISTICS=y
 CONFIG_NET_TCP=y
@@ -55,6 +58,7 @@ CONFIG_SCHED_CHILD_STATUS=y
 CONFIG_SCHED_HAVE_PARENT=y
 CONFIG_SCHED_HPWORK=y
 CONFIG_SCHED_WAITPID=y
+CONFIG_SIG_DEFAULT=y
 CONFIG_SIM_M32=y
 CONFIG_SIM_NET_BRIDGE=y
 CONFIG_SIM_RPTUN_MASTER=y
@@ -67,5 +71,6 @@ CONFIG_SYSTEM_CUTERM=y
 CONFIG_SYSTEM_CUTERM_DEFAULT_DEVICE="/dev/ttyproxy"
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_PING=y
+CONFIG_TTY_SIGINT=y
 CONFIG_USERMAIN_STACKSIZE=4096
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/include/netpacket/rpmsg.h b/include/netpacket/rpmsg.h
new file mode 100644
index 0000000..1dfd47d
--- /dev/null
+++ b/include/netpacket/rpmsg.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ * include/netpacket/rpmsg.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NETPACKET_RPMSG_H
+#define __INCLUDE_NETPACKET_RPMSG_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define RPMSG_SOCKET_CPU_SIZE           16
+#define RPMSG_SOCKET_NAME_SIZE          32
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+struct sockaddr_rpmsg
+{
+  sa_family_t rp_family;
+  char        rp_cpu[RPMSG_SOCKET_CPU_SIZE];
+  char        rp_name[RPMSG_SOCKET_NAME_SIZE];
+};
+
+#endif /* __INCLUDE_NETPACKET_RPMSG_H */
diff --git a/include/sys/socket.h b/include/sys/socket.h
index ba89a87..1d58cf1 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -50,6 +50,7 @@
 #define PF_BLUETOOTH  31         /* Bluetooth sockets */
 #define PF_IEEE802154 36         /* Low level IEEE 802.15.4 radio frame interface */
 #define PF_PKTRADIO   64         /* Low level packet radio interface */
+#define PF_RPMSG      65         /* Remote core communication */
 
 /* Supported Address Families. Opengroup.org requires only AF_UNSPEC,
  * AF_UNIX, AF_INET and AF_INET6.
@@ -67,6 +68,7 @@
 #define AF_BLUETOOTH   PF_BLUETOOTH
 #define AF_IEEE802154  PF_IEEE802154
 #define AF_PKTRADIO    PF_PKTRADIO
+#define AF_RPMSG       PF_RPMSG
 
 /* The socket created by socket() has the indicated type, which specifies
  * the communication semantics.
diff --git a/net/Kconfig b/net/Kconfig
index a8ff4ae..a3d5720 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -303,6 +303,7 @@ source "net/socket/Kconfig"
 source "net/inet/Kconfig"
 source "net/pkt/Kconfig"
 source "net/local/Kconfig"
+source "net/rpmsg/Kconfig"
 source "net/can/Kconfig"
 source "net/netlink/Kconfig"
 source "net/tcp/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index c63eae6..3e627e4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -36,6 +36,7 @@ include neighbor/Make.defs
 include igmp/Make.defs
 include pkt/Make.defs
 include local/Make.defs
+include rpmsg/Make.defs
 include mld/Make.defs
 include can/Make.defs
 include netlink/Make.defs
diff --git a/net/rpmsg/Kconfig b/net/rpmsg/Kconfig
new file mode 100644
index 0000000..4dca6f9
--- /dev/null
+++ b/net/rpmsg/Kconfig
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menu "Rpmsg Socket Support"
+	depends on NET
+
+config NET_RPMSG
+	bool "Rpmsg domain (remote) sockets"
+	select MM_CIRCBUF
+	default n
+	---help---
+		Enable or disable Rpmsg (aka remote) sockets.
+
+if NET_RPMSG
+
+config NET_RPMSG_RXBUF_SIZE
+	int "Rpmsg socket rx buffer size"
+	default 1024
+	---help---
+		Socket rpmsg rx buffer size, for recv slowly
+
+config NET_RPMSG_NPOLLWAITERS
+	int "Rpmsg socket number of poll waiters"
+	default 4
+	---help---
+		Socket rpmsg number of poll waiters
+
+endif # NET_RPMSG
+
+endmenu # Rpmsg Domain Sockets
diff --git a/net/rpmsg/Make.defs b/net/rpmsg/Make.defs
new file mode 100644
index 0000000..cde7e6f
--- /dev/null
+++ b/net/rpmsg/Make.defs
@@ -0,0 +1,32 @@
+############################################################################
+# net/rpmsg/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# Rpmsg domain socket source files
+
+ifeq ($(CONFIG_NET_RPMSG),y)
+
+NET_CSRCS += rpmsg_sockif.c
+
+# Include rpmsg domain socket build support
+
+DEPPATH += --dep-path rpmsg
+VPATH += :rpmsg
+
+endif # CONFIG_NET_RPMSG
diff --git a/net/rpmsg/rpmsg.h b/net/rpmsg/rpmsg.h
new file mode 100644
index 0000000..8d41bc9
--- /dev/null
+++ b/net/rpmsg/rpmsg.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ * net/rpmsg/rpmsg.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __NET_RPMSG_RPMSG_H
+#define __NET_RPMSG_RPMSG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/net/net.h>
+
+#ifdef CONFIG_NET_RPMSG
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#  define EXTERN extern "C"
+extern "C"
+{
+#else
+#  define EXTERN extern
+#endif
+
+EXTERN const struct sock_intf_s g_rpmsg_sockif;
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_RPMSG */
+#endif /* __NET_RPMSG_RPMSG_H */
diff --git a/net/rpmsg/rpmsg_sockif.c b/net/rpmsg/rpmsg_sockif.c
new file mode 100644
index 0000000..c66ec35
--- /dev/null
+++ b/net/rpmsg/rpmsg_sockif.c
@@ -0,0 +1,1192 @@
+/****************************************************************************
+ * net/rpmsg/rpmsg_sockif.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mm/circbuf.h>
+#include <nuttx/rptun/openamp.h>
+#include <nuttx/semaphore.h>
+
+#include <netinet/in.h>
+#include <netpacket/rpmsg.h>
+
+#include "socket/socket.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef MIN
+#  define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define RPMSG_SOCKET_CMD_SYNC       1
+#define RPMSG_SOCKET_CMD_DATA       2
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+begin_packed_struct struct rpmsg_socket_sync_s
+{
+  uint32_t                       cmd;
+  uint32_t                       size;
+} end_packed_struct;
+
+begin_packed_struct struct rpmsg_socket_data_s
+{
+  uint32_t                       cmd;
+  uint32_t                       pos;
+
+  /* Act data len, don't include len itself when SOCK_DGRAM */
+
+  uint32_t                       len;
+  char                           data[0];
+} end_packed_struct;
+
+struct rpmsg_socket_conn_s
+{
+  struct rpmsg_endpoint          ept;
+
+  struct sockaddr_rpmsg          rpaddr;
+  uint16_t                       crefs;
+
+  FAR struct pollfd              *fds[CONFIG_NET_RPMSG_NPOLLWAITERS];
+
+  sem_t                          sendsem;
+  sem_t                          sendlock;
+
+  sem_t                          recvsem;
+  sem_t                          recvlock;
+
+  FAR void                       *recvdata;
+  uint32_t                       recvlen;
+  FAR struct circbuf_s           recvbuf;
+
+  FAR struct rpmsg_socket_conn_s *next;
+
+  /* server listen-scoket listening: backlog > 0;
+   * server listen-scoket closed: backlog = -1;
+   * others: backlog = 0;
+   */
+
+  int                            backlog;
+
+  /* Flow control, descript send side */
+
+  uint32_t                       sendsize;
+  uint32_t                       sendpos;
+  uint32_t                       ackpos;
+
+  /* Flow control, descript recv side */
+
+  uint32_t                       recvpos;
+  uint32_t                       lastpos;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int        rpmsg_socket_setup(FAR struct socket *psock, int protocol);
+static sockcaps_t rpmsg_socket_sockcaps(FAR struct socket *psock);
+static void       rpmsg_socket_addref(FAR struct socket *psock);
+static int        rpmsg_socket_bind(FAR struct socket *psock,
+                    FAR const struct sockaddr *addr, socklen_t addrlen);
+static int        rpmsg_socket_getsockname(FAR struct socket *psock,
+                    FAR struct sockaddr *addr, FAR socklen_t *addrlen);
+static int        rpmsg_socket_getconnname(FAR struct socket *psock,
+                    FAR struct sockaddr *addr, FAR socklen_t *addrlen);
+static int        rpmsg_socket_listen(FAR struct socket *psock, int backlog);
+static int        rpmsg_socket_connect(FAR struct socket *psock,
+                    FAR const struct sockaddr *addr, socklen_t addrlen);
+static int        rpmsg_socket_accept(FAR struct socket *psock,
+                    FAR struct sockaddr *addr, FAR socklen_t *addrlen,
+                    FAR struct socket *newsock);
+static int        rpmsg_socket_poll(FAR struct socket *psock,
+                    FAR struct pollfd *fds, bool setup);
+static ssize_t    rpmsg_socket_sendmsg(FAR struct socket *psock,
+                    FAR struct msghdr *msg, int flags);
+static ssize_t    rpmsg_socket_recvmsg(FAR struct socket *psock,
+                    FAR struct msghdr *msg, int flags);
+static int        rpmsg_socket_close(FAR struct socket *psock);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct sock_intf_s g_rpmsg_sockif =
+{
+  rpmsg_socket_setup,       /* si_setup */
+  rpmsg_socket_sockcaps,    /* si_sockcaps */
+  rpmsg_socket_addref,      /* si_addref */
+  rpmsg_socket_bind,        /* si_bind */
+  rpmsg_socket_getsockname, /* si_getsockname */
+  rpmsg_socket_getconnname, /* si_getconnname */
+  rpmsg_socket_listen,      /* si_listen */
+  rpmsg_socket_connect,     /* si_connect */
+  rpmsg_socket_accept,      /* si_accept */
+  rpmsg_socket_poll,        /* si_poll */
+  rpmsg_socket_sendmsg,     /* si_sendmsg */
+  rpmsg_socket_recvmsg,     /* si_recvmsg */
+  rpmsg_socket_close        /* si_close */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static unsigned int g_rpmsg_id;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline void rpmsg_socket_lock(FAR sem_t *sem)
+{
+  net_lockedwait_uninterruptible(sem);
+}
+
+static inline void rpmsg_socket_unlock(FAR sem_t *sem)
+{
+  nxsem_post(sem);
+}
+
+static inline void rpmsg_socket_post(FAR sem_t *sem)
+{
+  int semcount;
+
+  nxsem_get_value(sem, &semcount);
+  if (semcount < 1)
+    {
+      nxsem_post(sem);
+    }
+}
+
+static void rpmsg_socket_pollnotify(FAR struct rpmsg_socket_conn_s *conn,
+                                    pollevent_t eventset)
+{
+  int i;
+
+  for (i = 0; i < CONFIG_NET_RPMSG_NPOLLWAITERS; i++)
+    {
+      FAR struct pollfd *fds = conn->fds[i];
+
+      if (fds)
+        {
+          fds->revents |= (fds->events & eventset);
+
+          if (fds->revents != 0)
+            {
+              rpmsg_socket_post(fds->sem);
+            }
+        }
+    }
+}
+
+static FAR struct rpmsg_socket_conn_s *rpmsg_socket_alloc(void)
+{
+  FAR struct rpmsg_socket_conn_s *conn;
+
+  conn = kmm_zalloc(sizeof(struct rpmsg_socket_conn_s));
+  if (!conn)
+    {
+      return NULL;
+    }
+
+  circbuf_init(&conn->recvbuf, NULL, 0);
+
+  nxsem_init(&conn->sendlock, 0, 1);
+  nxsem_init(&conn->recvlock, 0, 1);
+  nxsem_init(&conn->sendsem, 0, 0);
+  nxsem_init(&conn->recvsem, 0, 0);
+  nxsem_set_protocol(&conn->sendsem, SEM_PRIO_NONE);
+  nxsem_set_protocol(&conn->recvsem, SEM_PRIO_NONE);
+
+  conn->crefs = 1;
+  return conn;
+}
+
+static void rpmsg_socket_free(FAR struct rpmsg_socket_conn_s *conn)
+{
+  circbuf_uninit(&conn->recvbuf);
+
+  nxsem_destroy(&conn->recvlock);
+  nxsem_destroy(&conn->sendlock);
+  nxsem_destroy(&conn->sendsem);
+  nxsem_destroy(&conn->recvsem);
+
+  kmm_free(conn);
+}
+
+static int rpmsg_socket_wakeup(FAR struct rpmsg_socket_conn_s *conn)
+{
+  struct rpmsg_socket_data_s msg;
+  uint32_t space;
+  int ret = 0;
+
+  space = conn->recvpos - conn->lastpos;
+
+  if (space > circbuf_size(&conn->recvbuf) / 2)
+    {
+      msg.cmd = RPMSG_SOCKET_CMD_DATA;
+      msg.pos = conn->recvpos;
+      msg.len = 0;
+      ret = rpmsg_send(&conn->ept, &msg, sizeof(msg));
+      if (ret >= 0)
+        {
+          conn->lastpos = conn->recvpos;
+        }
+    }
+
+  return ret;
+}
+
+static int rpmsg_socket_sync(FAR struct rpmsg_socket_conn_s *conn,
+                             unsigned int timeout)
+{
+  struct rpmsg_socket_sync_s msg;
+  int ret;
+
+  msg.cmd  = RPMSG_SOCKET_CMD_SYNC;
+  msg.size = circbuf_size(&conn->recvbuf);
+
+  ret = rpmsg_send(&conn->ept, &msg, sizeof(msg));
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (conn->sendsize == 0)
+    {
+      ret = net_timedwait(&conn->sendsem, timeout);
+    }
+
+  return ret;
+}
+
+static inline uint32_t rpmsg_socket_get_space(
+                        FAR struct rpmsg_socket_conn_s *conn)
+{
+  return conn->sendsize - (conn->sendpos - conn->ackpos);
+}
+
+static int rpmsg_socket_ept_cb(FAR struct rpmsg_endpoint *ept,
+                               FAR void *data, size_t len, uint32_t src,
+                               FAR void *priv)
+{
+  FAR struct rpmsg_socket_conn_s *conn = ept->priv;
+  FAR struct rpmsg_socket_sync_s *head = data;
+
+  if (head->cmd == RPMSG_SOCKET_CMD_SYNC)
+    {
+      conn->sendsize = head->size;
+      rpmsg_socket_post(&conn->sendsem);
+    }
+  else
+    {
+      FAR struct rpmsg_socket_data_s *msg = data;
+      FAR uint8_t *buf = (FAR uint8_t *)msg->data;
+
+      rpmsg_socket_lock(&conn->sendlock);
+
+      conn->ackpos = msg->pos;
+
+      if (rpmsg_socket_get_space(conn) > 0)
+        {
+          rpmsg_socket_post(&conn->sendsem);
+          rpmsg_socket_pollnotify(conn, POLLOUT);
+        }
+
+      rpmsg_socket_unlock(&conn->sendlock);
+
+      if (len > sizeof(*msg))
+        {
+          len -= sizeof(*msg);
+
+          DEBUGASSERT(len == msg->len || len == msg->len + sizeof(uint32_t));
+
+          rpmsg_socket_lock(&conn->recvlock);
+
+          if (conn->recvdata)
+            {
+              conn->recvlen = MIN(conn->recvlen, msg->len);
+
+              if (len == msg->len)
+                {
+                  /* SOCOK_STREAM */
+
+                  conn->recvpos += conn->recvlen;
+                  memcpy(conn->recvdata, buf, conn->recvlen);
+                  buf += conn->recvlen;
+                  len -= conn->recvlen;
+                }
+              else
+                {
+                  /* SOCOK_DGRAM */
+
+                  conn->recvpos += len;
+                  memcpy(conn->recvdata, buf + sizeof(uint32_t),
+                         conn->recvlen);
+                  len = 0;
+                }
+
+              conn->recvdata = NULL;
+              nxsem_post(&conn->recvsem);
+            }
+
+          if (len > 0)
+            {
+              ssize_t written;
+
+              written = circbuf_write(&conn->recvbuf, buf, len);
+              if (written != len)
+                {
+                  nerr("circbuf_write overflow, %d, %d\n", written, len);
+                }
+
+              rpmsg_socket_pollnotify(conn, POLLIN);
+            }
+
+          rpmsg_socket_unlock(&conn->recvlock);
+        }
+    }
+
+  return 0;
+}
+
+static inline void rpmsg_socket_destroy_ept(
+                    FAR struct rpmsg_socket_conn_s *conn)
+{
+  if (conn && conn->ept.rdev)
+    {
+      if (conn->backlog)
+        {
+          /* Listen socket */
+
+          conn->backlog = -1;
+        }
+
+      rpmsg_destroy_ept(&conn->ept);
+      rpmsg_socket_post(&conn->sendsem);
+      rpmsg_socket_post(&conn->recvsem);
+      rpmsg_socket_pollnotify(conn, POLLIN | POLLOUT);
+    }
+}
+
+static void rpmsg_socket_ns_unbind(FAR struct rpmsg_endpoint *ept)
+{
+  rpmsg_socket_destroy_ept(ept->priv);
+}
+
+static void rpmsg_socket_device_created(FAR struct rpmsg_device *rdev,
+                                        FAR void *priv)
+{
+  FAR struct rpmsg_socket_conn_s *conn = priv;
+
+  if (conn->ept.rdev)
+    {
+      return;
+    }
+
+  if (strcmp(conn->rpaddr.rp_cpu, rpmsg_get_cpuname(rdev)) == 0)
+    {
+      conn->ept.priv = conn;
+
+      rpmsg_create_ept(&conn->ept, rdev, conn->rpaddr.rp_name,
+                       RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
+                       rpmsg_socket_ept_cb, rpmsg_socket_ns_unbind);
+    }
+}
+
+static void rpmsg_socket_device_destroy(FAR struct rpmsg_device *rdev,
+                                        FAR void *priv)
+{
+  FAR struct rpmsg_socket_conn_s *conn = priv;
+
+  if (strcmp(conn->rpaddr.rp_cpu, rpmsg_get_cpuname(rdev)) == 0)
+    {
+      rpmsg_socket_destroy_ept(conn);
+    }
+}
+
+static void rpmsg_socket_ns_bind(FAR struct rpmsg_device *rdev,
+                                 FAR void *priv, FAR const char *name,
+                                 uint32_t dest)
+{
+  FAR struct rpmsg_socket_conn_s *server = priv;
+  FAR struct rpmsg_socket_conn_s *tmp;
+  FAR struct rpmsg_socket_conn_s *new;
+  int ret;
+  int i = 0;
+
+  if (strncmp(name, server->rpaddr.rp_name,
+              strlen(server->rpaddr.rp_name)))
+    {
+      return;
+    }
+
+  if (strlen(server->rpaddr.rp_cpu) &&
+          strcmp(server->rpaddr.rp_cpu, rpmsg_get_cpuname(rdev)))
+    {
+      /* Bind specific CPU, then only listen that CPU */
+
+      return;
+    }
+
+  for (tmp = server; tmp->next; tmp = tmp->next)
+    {
+      if (++i > server->backlog)
+        {
+          return;
+        }
+    }
+
+  new = rpmsg_socket_alloc();
+  if (!new)
+    {
+      return;
+    }
+
+  ret = circbuf_resize(&new->recvbuf, CONFIG_NET_RPMSG_RXBUF_SIZE);
+  if (ret < 0)
+    {
+      rpmsg_socket_free(new);
+      return;
+    }
+
+  new->ept.priv = new;
+  ret = rpmsg_create_ept(&new->ept, rdev, name,
+                         RPMSG_ADDR_ANY, dest,
+                         rpmsg_socket_ept_cb, rpmsg_socket_ns_unbind);
+  if (ret < 0)
+    {
+      rpmsg_socket_free(new);
+      return;
+    }
+
+  strcpy(new->rpaddr.rp_cpu, rpmsg_get_cpuname(rdev));
+  strcpy(new->rpaddr.rp_name, name);
+
+  tmp->next = new;
+
+  rpmsg_socket_post(&server->recvsem);
+  rpmsg_socket_pollnotify(server, POLLIN);
+}
+
+static int rpmsg_socket_getaddr(FAR struct rpmsg_socket_conn_s *conn,
+                                FAR struct sockaddr *addr,
+                                FAR socklen_t *addrlen)
+{
+  if (!addr || *addrlen < sizeof(struct sockaddr_rpmsg))
+    {
+      return -EINVAL;
+    }
+
+  memcpy(addr, &conn->rpaddr, sizeof(struct sockaddr_rpmsg));
+  *addrlen = sizeof(struct sockaddr_rpmsg);
+
+  return 0;
+}
+
+static int rpmsg_socket_setaddr(FAR struct rpmsg_socket_conn_s *conn,
+                                FAR const struct sockaddr *addr,
+                                socklen_t addrlen, bool suffix)
+{
+  FAR struct sockaddr_rpmsg *rpaddr = (FAR struct sockaddr_rpmsg *)addr;
+
+  if (rpaddr->rp_family != AF_RPMSG ||
+      addrlen != sizeof(struct sockaddr_rpmsg))
+    {
+      return -EINVAL;
+    }
+
+  memcpy(&conn->rpaddr, rpaddr, sizeof(struct sockaddr_rpmsg));
+
+  if (suffix)
+    {
+      size_t len;
+
+      rpaddr = &conn->rpaddr;
+      len = strlen(rpaddr->rp_name);
+      snprintf(&rpaddr->rp_name[len], RPMSG_SOCKET_NAME_SIZE - len - 1,
+               "%u", g_rpmsg_id++);
+    }
+
+  return 0;
+}
+
+static int rpmsg_socket_setup(FAR struct socket *psock, int protocol)
+{
+  FAR struct rpmsg_socket_conn_s *conn;
+
+  conn = rpmsg_socket_alloc();
+  if (!conn)
+    {
+      return -ENOMEM;
+    }
+
+  psock->s_conn = conn;
+  return 0;
+}
+
+static sockcaps_t rpmsg_socket_sockcaps(FAR struct socket *psock)
+{
+  return SOCKCAP_NONBLOCKING;
+}
+
+static void rpmsg_socket_addref(FAR struct socket *psock)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+
+  conn->crefs++;
+}
+
+static int rpmsg_socket_bind(FAR struct socket *psock,
+                            FAR const struct sockaddr *addr,
+                            socklen_t addrlen)
+{
+  return rpmsg_socket_setaddr(psock->s_conn, addr, addrlen, false);
+}
+
+static int rpmsg_socket_getsockname(FAR struct socket *psock,
+                                   FAR struct sockaddr *addr,
+                                   FAR socklen_t *addrlen)
+{
+  return rpmsg_socket_getaddr(psock->s_conn, addr, addrlen);
+}
+
+static int rpmsg_socket_getconnname(FAR struct socket *psock,
+                                    FAR struct sockaddr *addr,
+                                    FAR socklen_t *addrlen)
+{
+  return rpmsg_socket_getsockname(psock, addr, addrlen);
+}
+
+static int rpmsg_socket_listen(FAR struct socket *psock, int backlog)
+{
+  FAR struct rpmsg_socket_conn_s *server = psock->s_conn;
+
+  if (psock->s_type != SOCK_STREAM)
+    {
+      return -ENOSYS;
+    }
+
+  if (!_SS_ISBOUND(psock->s_flags) || backlog <= 0)
+    {
+      return -EINVAL;
+    }
+
+  server->backlog = backlog;
+  return rpmsg_register_callback(server,
+                                NULL,
+                                NULL,
+                                rpmsg_socket_ns_bind);
+}
+
+static int rpmsg_socket_connect_internal(FAR struct socket *psock)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+  unsigned int timeout;
+  unsigned int tc;
+  int ret;
+
+  ret = circbuf_resize(&conn->recvbuf, CONFIG_NET_RPMSG_RXBUF_SIZE);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = rpmsg_register_callback(conn,
+                                rpmsg_socket_device_created,
+                                rpmsg_socket_device_destroy,
+                                NULL);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret     = -ETIMEDOUT;
+  timeout = _SO_TIMEOUT(psock->s_rcvtimeo);
+
+  for (tc = 0; tc < timeout * 1000; )
+    {
+      ret = rpmsg_socket_sync(conn, timeout);
+      if (ret != RPMSG_ERR_ADDR)
+        {
+          break;
+        }
+
+      if (timeout != UINT_MAX)
+        {
+          tc += RPMSG_TICK_COUNT;
+        }
+    }
+
+  if (ret < 0)
+    {
+      rpmsg_unregister_callback(conn,
+                                rpmsg_socket_device_created,
+                                rpmsg_socket_device_destroy,
+                                NULL);
+    }
+
+  return ret;
+}
+
+static int rpmsg_socket_connect(FAR struct socket *psock,
+                                FAR const struct sockaddr *addr,
+                                socklen_t addrlen)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+  int ret;
+
+  if (_SS_ISCONNECTED(psock->s_flags))
+    {
+      return -EISCONN;
+    }
+
+  ret = rpmsg_socket_setaddr(conn, addr, addrlen,
+                             psock->s_type == SOCK_STREAM);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return rpmsg_socket_connect_internal(psock);
+}
+
+static int rpmsg_socket_accept(FAR struct socket *psock,
+                               FAR struct sockaddr *addr,
+                               FAR socklen_t *addrlen,
+                               FAR struct socket *newsock)
+{
+  FAR struct rpmsg_socket_conn_s *server = psock->s_conn;
+  int ret = 0;
+
+  if (server->backlog == -1)
+    {
+      return -ECONNRESET;
+    }
+
+  if (!_SS_ISLISTENING(psock->s_flags))
+    {
+      return -EINVAL;
+    }
+
+  while (1)
+    {
+      if (server->next)
+        {
+          FAR struct rpmsg_socket_conn_s *conn = server->next;
+
+          server->next = conn->next;
+          conn->next = NULL;
+
+          rpmsg_socket_sync(conn, _SO_TIMEOUT(psock->s_rcvtimeo));
+
+          rpmsg_register_callback(conn,
+                                  rpmsg_socket_device_created,
+                                  rpmsg_socket_device_destroy,
+                                  NULL);
+
+          newsock->s_domain = psock->s_domain;
+          newsock->s_sockif = psock->s_sockif;
+          newsock->s_type   = SOCK_STREAM;
+          newsock->s_conn   = conn;
+
+          rpmsg_socket_getaddr(conn, addr, addrlen);
+
+          break;
+        }
+      else
+        {
+          if (_SS_ISNONBLOCK(psock->s_flags))
+            {
+              ret = -EAGAIN;
+              break;
+            }
+          else
+            {
+              ret = net_lockedwait(&server->recvsem);
+              if (server->backlog == -1)
+                {
+                  ret = -ECONNRESET;
+                }
+
+              if (ret < 0)
+                {
+                  break;
+                }
+            }
+        }
+    }
+
+  return ret;
+}
+
+static int rpmsg_socket_poll(FAR struct socket *psock,
+                             FAR struct pollfd *fds, bool setup)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+  pollevent_t eventset = 0;
+  int ret = 0;
+  int i;
+
+  if (setup)
+    {
+      for (i = 0; i < CONFIG_NET_RPMSG_NPOLLWAITERS; i++)
+        {
+          /* Find an available slot */
+
+          if (!conn->fds[i])
+            {
+              /* Bind the poll structure and this slot */
+
+              conn->fds[i] = fds;
+              fds->priv    = &conn->fds[i];
+              break;
+            }
+        }
+
+      if (i >= CONFIG_NET_RPMSG_NPOLLWAITERS)
+        {
+          fds->priv = NULL;
+          ret       = -EBUSY;
+          goto errout;
+        }
+
+      /* Immediately notify on any of the requested events */
+
+      if (_SS_ISLISTENING(psock->s_flags))
+        {
+          if (conn->backlog == -1)
+            {
+              ret = -ECONNRESET;
+              goto errout;
+            }
+
+          if (conn->next)
+            {
+              eventset |= (fds->events & POLLIN);
+            }
+        }
+      else if (_SS_ISCONNECTED(psock->s_flags))
+        {
+          if (!conn->ept.rdev)
+            {
+              ret = -ECONNRESET;
+              goto errout;
+            }
+
+          rpmsg_socket_lock(&conn->sendlock);
+
+          if (rpmsg_socket_get_space(conn) > 0)
+            {
+              eventset |= (fds->events & POLLOUT);
+            }
+
+          rpmsg_socket_unlock(&conn->sendlock);
+
+          rpmsg_socket_lock(&conn->recvlock);
+
+          if (!circbuf_is_empty(&conn->recvbuf))
+            {
+              eventset |= (fds->events & POLLIN);
+            }
+
+          rpmsg_socket_unlock(&conn->recvlock);
+        }
+      else
+        {
+          ret = -EPERM;
+          goto errout;
+        }
+
+      if (eventset)
+        {
+          rpmsg_socket_pollnotify(conn, eventset);
+        }
+    }
+  else if (fds->priv != NULL)
+    {
+      for (i = 0; i < CONFIG_NET_RPMSG_NPOLLWAITERS; i++)
+        {
+          if (fds == conn->fds[i])
+            {
+              conn->fds[i] = NULL;
+              fds->priv = NULL;
+              break;
+            }
+        }
+    }
+
+errout:
+  return ret;
+}
+
+static ssize_t rpmsg_socket_send_continuous(FAR struct socket *psock,
+                                            FAR const void *buf,
+                                            size_t len)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+  FAR const char *cur = buf;
+  size_t written = 0;
+  int ret = 0;
+
+  rpmsg_socket_lock(&conn->sendlock);
+
+  while (written < len)
+    {
+      uint32_t block = MIN(len - written, rpmsg_socket_get_space(conn));
+      FAR struct rpmsg_socket_data_s *msg;
+      uint32_t ipcsize;
+
+      if (block == 0)
+        {
+          if (!_SS_ISNONBLOCK(psock->s_flags))
+            {
+              rpmsg_socket_unlock(&conn->sendlock);
+
+              ret = net_timedwait(&conn->sendsem,
+                                  _SO_TIMEOUT(psock->s_sndtimeo));
+              if (!conn->ept.rdev)
+                {
+                  ret = -ECONNRESET;
+                }
+
+              rpmsg_socket_lock(&conn->sendlock);
+
+              if (ret < 0)
+                {
+                  break;
+                }
+            }
+          else
+            {
+              ret = -EAGAIN;
+              break;
+            }
+        }
+
+      msg = rpmsg_get_tx_payload_buffer(&conn->ept, &ipcsize, true);
+      if (!msg)
+        {
+          ret = -EINVAL;
+          break;
+        }
+
+      block = MIN(block, ipcsize - sizeof(*msg));
+
+      msg->cmd = RPMSG_SOCKET_CMD_DATA;
+      msg->pos = conn->recvpos;
+      msg->len = block;
+      memcpy(msg->data, cur, block);
+
+      conn->lastpos  = conn->recvpos;
+      conn->sendpos += msg->len;
+
+      ret = rpmsg_send_nocopy(&conn->ept, msg, block + sizeof(*msg));
+      if (ret < 0)
+        {
+          break;
+        }
+
+      written += block;
+      cur     += block;
+    }
+
+  rpmsg_socket_unlock(&conn->sendlock);
+
+  return written ? written : ret;
+}
+
+static ssize_t rpmsg_socket_send_single(FAR struct socket *psock,
+                                        FAR const void *buf, size_t len)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+  FAR struct rpmsg_socket_data_s *msg;
+  uint32_t total = len + sizeof(*msg) + sizeof(uint32_t);
+  uint32_t ipcsize;
+  int ret;
+
+  if (total > conn->sendsize)
+    {
+      return -EFBIG;
+    }
+
+  rpmsg_socket_lock(&conn->sendlock);
+
+  while (total - sizeof(*msg) > rpmsg_socket_get_space(conn))
+    {
+      if (!_SS_ISNONBLOCK(psock->s_flags))
+        {
+          rpmsg_socket_unlock(&conn->sendlock);
+
+          ret = net_timedwait(&conn->sendsem,
+                              _SO_TIMEOUT(psock->s_sndtimeo));
+          if (!conn->ept.rdev)
+            {
+              ret = -ECONNRESET;
+            }
+
+          rpmsg_socket_lock(&conn->sendlock);
+
+          if (ret < 0)
+            {
+              goto out;
+            }
+        }
+      else
+        {
+          ret = -EAGAIN;
+          goto out;
+        }
+    }
+
+  msg = rpmsg_get_tx_payload_buffer(&conn->ept, &ipcsize, true);
+  if (!msg)
+    {
+      ret = -EINVAL;
+      goto out;
+    }
+
+  if (total > ipcsize)
+    {
+      total = ipcsize;
+      len   = ipcsize - sizeof(*msg) + sizeof(uint32_t);
+    }
+
+  /* SOCK_DGRAM need write len to buffer */
+
+  msg->cmd = RPMSG_SOCKET_CMD_DATA;
+  msg->pos = conn->recvpos;
+  msg->len = len;
+  memcpy(msg->data, &len, sizeof(uint32_t));
+  memcpy(msg->data + sizeof(uint32_t), buf, len);
+
+  conn->lastpos  = conn->recvpos;
+  conn->sendpos += len + sizeof(uint32_t);
+
+  ret = rpmsg_send_nocopy(&conn->ept, msg, total);
+out:
+  rpmsg_socket_unlock(&conn->sendlock);
+  return ret > 0 ? len : ret;
+}
+
+static ssize_t rpmsg_socket_send_internal(FAR struct socket *psock,
+                                          FAR const void *buf,
+                                          size_t len, int flags)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+
+  if (!conn->ept.rdev)
+    {
+      /* return ECONNRESET if lower IPC closed */
+
+      return -ECONNRESET;
+    }
+
+  if (psock->s_type == SOCK_STREAM)
+    {
+      return rpmsg_socket_send_continuous(psock, buf, len);
+    }
+  else
+    {
+      return rpmsg_socket_send_single(psock, buf, len);
+    }
+}
+
+static ssize_t rpmsg_socket_sendmsg(FAR struct socket *psock,
+                                    FAR struct msghdr *msg, int flags)
+{
+  const FAR void *buf = msg->msg_iov->iov_base;
+  size_t len = msg->msg_iov->iov_len;
+  const FAR struct sockaddr *to = msg->msg_name;
+  socklen_t tolen = msg->msg_namelen;
+  ssize_t ret;
+
+  /* Validity check, only single iov supported */
+
+  if (msg->msg_iovlen != 1)
+    {
+      return -ENOTSUP;
+    }
+
+  if (!_SS_ISCONNECTED(psock->s_flags))
+    {
+      if (to == NULL)
+        {
+          return -ENOTCONN;
+        }
+
+      ret = rpmsg_socket_connect(psock, to, tolen);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+
+  return rpmsg_socket_send_internal(psock, buf, len, flags);
+}
+
+static ssize_t rpmsg_socket_recvmsg(FAR struct socket *psock,
+                                    FAR struct msghdr *msg, int flags)
+{
+  FAR void *buf = msg->msg_iov->iov_base;
+  size_t len = msg->msg_iov->iov_len;
+  FAR struct sockaddr *from = msg->msg_name;
+  FAR socklen_t *fromlen = &msg->msg_namelen;
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+  ssize_t ret;
+
+  if (psock->s_type == SOCK_DGRAM && _SS_ISBOUND(psock->s_flags)
+          && !_SS_ISCONNECTED(psock->s_flags))
+    {
+      ret = rpmsg_socket_connect_internal(psock);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      psock->s_flags |= _SF_CONNECTED;
+    }
+
+  if (!_SS_ISCONNECTED(psock->s_flags))
+    {
+      return -EISCONN;
+    }
+
+  rpmsg_socket_lock(&conn->recvlock);
+
+  if (psock->s_type == SOCK_DGRAM)
+    {
+      uint32_t datalen;
+
+      ret = circbuf_read(&conn->recvbuf, &datalen, sizeof(uint32_t));
+      if (ret > 0)
+        {
+          ret = circbuf_read(&conn->recvbuf, buf, MIN(datalen, len));
+          if (ret > 0 && datalen > ret)
+            {
+              circbuf_skip(&conn->recvbuf, datalen - ret);
+            }
+
+          conn->recvpos += datalen + sizeof(uint32_t);
+        }
+    }
+  else
+    {
+      ret = circbuf_read(&conn->recvbuf, buf, len);
+      conn->recvpos +=  ret > 0 ? ret : 0;
+    }
+
+  if (ret > 0)
+    {
+      rpmsg_socket_wakeup(conn);
+      goto out;
+    }
+
+  if (!conn->ept.rdev)
+    {
+      /* return EOF if lower IPC closed */
+
+      ret = 0;
+      goto out;
+    }
+
+  if (_SS_ISNONBLOCK(psock->s_flags))
+    {
+      ret = -EAGAIN;
+      goto out;
+    }
+
+  conn->recvdata = buf;
+  conn->recvlen  = len;
+
+  rpmsg_socket_unlock(&conn->recvlock);
+
+  ret = net_timedwait(&conn->recvsem, _SO_TIMEOUT(psock->s_rcvtimeo));
+  if (!conn->ept.rdev)
+    {
+      ret = -ECONNRESET;
+    }
+
+  rpmsg_socket_lock(&conn->recvlock);
+
+  if (!conn->recvdata)
+    {
+      ret = conn->recvlen;
+      rpmsg_socket_wakeup(conn);
+    }
+  else
+    {
+      conn->recvdata = NULL;
+    }
+
+out:
+  rpmsg_socket_unlock(&conn->recvlock);
+
+  if (ret > 0)
+    {
+      rpmsg_socket_getaddr(conn, from, fromlen);
+    }
+
+  return ret;
+}
+
+static int rpmsg_socket_close(FAR struct socket *psock)
+{
+  FAR struct rpmsg_socket_conn_s *conn = psock->s_conn;
+
+  if (conn->crefs > 1)
+    {
+      conn->crefs--;
+      return 0;
+    }
+
+  if (conn->backlog)
+    {
+      rpmsg_unregister_callback(conn,
+                                NULL,
+                                NULL,
+                                rpmsg_socket_ns_bind);
+    }
+  else
+    {
+      rpmsg_unregister_callback(conn,
+                                rpmsg_socket_device_created,
+                                rpmsg_socket_device_destroy,
+                                NULL);
+    }
+
+  rpmsg_socket_destroy_ept(conn);
+  rpmsg_socket_free(conn);
+  return 0;
+}
diff --git a/net/socket/net_sockif.c b/net/socket/net_sockif.c
index efdae05..ea8ccdc 100644
--- a/net/socket/net_sockif.c
+++ b/net/socket/net_sockif.c
@@ -32,6 +32,7 @@
 
 #include "inet/inet.h"
 #include "local/local.h"
+#include "rpmsg/rpmsg.h"
 #include "can/can.h"
 #include "netlink/netlink.h"
 #include "pkt/pkt.h"
@@ -120,6 +121,12 @@ net_sockif(sa_family_t family, int type, int protocol)
       break;
 #endif
 
+#ifdef CONFIG_NET_RPMSG
+    case PF_RPMSG:
+      sockif = &g_rpmsg_sockif;
+      break;
+#endif
+
     default:
       nerr("ERROR: Address family unsupported: %d\n", family);
     }
diff --git a/net/socket/socket.c b/net/socket/socket.c
index 281e015..5041ab4 100644
--- a/net/socket/socket.c
+++ b/net/socket/socket.c
@@ -100,7 +100,7 @@ int psock_socket(int domain, int type, int protocol,
   psock->s_type   = type;
 
 #ifdef CONFIG_NET_USRSOCK
-  if (domain != PF_LOCAL && domain != PF_UNSPEC)
+  if (domain != PF_LOCAL && domain != PF_UNSPEC && domain != PF_RPMSG)
     {
       /* Handle special setup for USRSOCK sockets (user-space networking
        * stack).