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).