You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/06/02 14:09:21 UTC
[incubator-nuttx] 03/31: net/: Add WIP initial framework for
SocketCAN sockets.
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch SocketCAN
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 46c67a47a0d24cb9ea8939d1c2ce8ff9b1474f47
Author: Gregory Nutt <gn...@nuttx.org>
AuthorDate: Thu Feb 13 09:59:00 2020 -0600
net/: Add WIP initial framework for SocketCAN sockets.
---
net/Kconfig | 1 +
net/Makefile | 1 +
net/can/Kconfig | 26 ++
net/can/Make.defs | 32 ++
net/can/can.h | 154 +++++++++
net/can/can_conn.c | 225 ++++++++++++++
net/can/can_sockif.c | 810 ++++++++++++++++++++++++++++++++++++++++++++++++
net/net_initialize.c | 7 +
net/socket/net_sockif.c | 7 +
9 files changed, 1263 insertions(+)
diff --git a/net/Kconfig b/net/Kconfig
index fed3d01..70cacf6 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -344,6 +344,7 @@ source "net/socket/Kconfig"
source "net/inet/Kconfig"
source "net/pkt/Kconfig"
source "net/local/Kconfig"
+source "net/can/Kconfig"
source "net/netlink/Kconfig"
source "net/tcp/Kconfig"
source "net/udp/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index 077d035..f8ffe85 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -52,6 +52,7 @@ include igmp/Make.defs
include pkt/Make.defs
include local/Make.defs
include mld/Make.defs
+include can/Make.defs
include netlink/Make.defs
include tcp/Make.defs
include udp/Make.defs
diff --git a/net/can/Kconfig b/net/can/Kconfig
new file mode 100644
index 0000000..2ae1f7b
--- /dev/null
+++ b/net/can/Kconfig
@@ -0,0 +1,26 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menu "SocketCAN Support"
+
+config NET_CAN
+ bool "SocketCAN support"
+ default n
+ ---help---
+ Enable support for SocketCAN sockets that will permit.
+
+ This logic is a WIP. Currently only fragmentary support is
+ available, not enough to actually do anything of consequence.
+
+if NET_CAN
+
+config CAN_CONNS
+ int "Number of CAN connections"
+ default 4
+ ---help---
+ Maximum number of CAN connections (all tasks).
+
+endif # NET_CAN
+endmenu # CAN Socket Support
diff --git a/net/can/Make.defs b/net/can/Make.defs
new file mode 100644
index 0000000..bb9ef9f
--- /dev/null
+++ b/net/can/Make.defs
@@ -0,0 +1,32 @@
+############################################################################
+# net/can/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.
+#
+############################################################################
+
+# Logic specific to SocketCAN socket support
+
+ifeq ($(CONFIG_NET_CAN),y)
+
+SOCK_CSRCS += can_sockif.c
+NET_CSRCS += can_conn.c
+
+# Include can build support
+
+DEPPATH += --dep-path can
+VPATH += :can
+endif
diff --git a/net/can/can.h b/net/can/can.h
new file mode 100644
index 0000000..6f41ce9
--- /dev/null
+++ b/net/can/can.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+ * net/can/can.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_CAN_CAN_H
+#define __NET_CAN_CAN_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <poll.h>
+
+#include <netpacket/can.h>
+#include <nuttx/semaphore.h>
+
+#include "devif/devif.h"
+#include "socket/socket.h"
+
+#ifdef CONFIG_NET_CAN
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* This "connection" structure describes the underlying state of the socket. */
+
+struct can_conn_s
+{
+ /* Common prologue of all connection structures. */
+
+ dq_entry_t node; /* Supports a doubly linked list */
+
+ /* This is a list of NetLink connection callbacks. Each callback
+ * represents a thread that is stalled, waiting for a device-specific
+ * event.
+ */
+
+ FAR struct devif_callback_s *list; /* NetLink callbacks */
+
+ /* CAN-specific content follows */
+
+ uint8_t protocol; /* Selected CAN protocol */
+ int16_t crefs; /* Reference count */
+
+ /* poll() support */
+
+ FAR sem_t *pollsem; /* Used to wakeup poll() */
+ FAR pollevent_t *pollevent; /* poll() wakeup event */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+# define EXTERN extern "C"
+extern "C"
+{
+#else
+# define EXTERN extern
+#endif
+
+EXTERN const struct sock_intf_s g_can_sockif;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct sockaddr_can; /* Forward reference */
+
+/****************************************************************************
+ * Name: can_initialize()
+ *
+ * Description:
+ * Initialize the NetLink connection structures. Called once and only
+ * from the networking layer.
+ *
+ ****************************************************************************/
+
+void can_initialize(void);
+
+/****************************************************************************
+ * Name: can_alloc()
+ *
+ * Description:
+ * Allocate a new, uninitialized NetLink connection structure. This is
+ * normally something done by the implementation of the socket() API
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_alloc(void);
+
+/****************************************************************************
+ * Name: can_free()
+ *
+ * Description:
+ * Free a NetLink connection structure that is no longer in use. This should
+ * be done by the implementation of close().
+ *
+ ****************************************************************************/
+
+void can_free(FAR struct can_conn_s *conn);
+
+/****************************************************************************
+ * Name: can_nextconn()
+ *
+ * Description:
+ * Traverse the list of allocated NetLink connections
+ *
+ * Assumptions:
+ * This function is called from NetLink device logic.
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
+
+/****************************************************************************
+ * Name: can_active()
+ *
+ * Description:
+ * Find a connection structure that is the appropriate connection for the
+ * provided NetLink address
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_active(FAR struct sockaddr_can *addr);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_NET_CAN */
+#endif /* __NET_CAN_CAN_H */
diff --git a/net/can/can_conn.c b/net/can/can_conn.c
new file mode 100644
index 0000000..77733b3
--- /dev/null
+++ b/net/can/can_conn.c
@@ -0,0 +1,225 @@
+/****************************************************************************
+ * net/can/can_conn.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 <stdint.h>
+#include <string.h>
+#include <queue.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/irq.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/net/netconfig.h>
+#include <nuttx/net/net.h>
+
+#include "utils/utils.h"
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CAN
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The array containing all NetLink connections. */
+
+static struct can_conn_s g_can_connections[CONFIG_CAN_CONNS];
+
+/* A list of all free NetLink connections */
+
+static dq_queue_t g_free_can_connections;
+static sem_t g_free_sem;
+
+/* A list of all allocated NetLink connections */
+
+static dq_queue_t g_active_can_connections;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: _can_semtake() and _can_semgive()
+ *
+ * Description:
+ * Take/give semaphore
+ *
+ ****************************************************************************/
+
+static void _can_semtake(FAR sem_t *sem)
+{
+ net_lockedwait_uninterruptible(sem);
+}
+
+static void _can_semgive(FAR sem_t *sem)
+{
+ nxsem_post(sem);
+}
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: can_initialize()
+ *
+ * Description:
+ * Initialize the User Socket connection structures. Called once and only
+ * from the networking layer.
+ *
+ ****************************************************************************/
+
+void can_initialize(void)
+{
+ int i;
+
+ /* Initialize the queues */
+
+ dq_init(&g_free_can_connections);
+ dq_init(&g_active_can_connections);
+ nxsem_init(&g_free_sem, 0, 1);
+
+ for (i = 0; i < CONFIG_CAN_CONNS; i++)
+ {
+ FAR struct can_conn_s *conn = &g_can_connections[i];
+
+ /* Mark the connection closed and move it to the free list */
+
+ memset(conn, 0, sizeof(*conn));
+ dq_addlast(&conn->node, &g_free_can_connections);
+ }
+}
+
+/****************************************************************************
+ * Name: can_alloc()
+ *
+ * Description:
+ * Allocate a new, uninitialized NetLink connection structure. This is
+ * normally something done by the implementation of the socket() API
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_alloc(void)
+{
+ FAR struct can_conn_s *conn;
+
+ /* The free list is protected by a semaphore (that behaves like a mutex). */
+
+ _can_semtake(&g_free_sem);
+ conn = (FAR struct can_conn_s *)dq_remfirst(&g_free_can_connections);
+ if (conn != NULL)
+ {
+ /* Make sure that the connection is marked as uninitialized */
+
+ memset(conn, 0, sizeof(*conn));
+
+ /* Enqueue the connection into the active list */
+
+ dq_addlast(&conn->node, &g_active_can_connections);
+ }
+
+ _can_semgive(&g_free_sem);
+ return conn;
+}
+
+/****************************************************************************
+ * Name: can_free()
+ *
+ * Description:
+ * Free a NetLink connection structure that is no longer in use. This should
+ * be done by the implementation of close().
+ *
+ ****************************************************************************/
+
+void can_free(FAR struct can_conn_s *conn)
+{
+ /* The free list is protected by a semaphore (that behaves like a mutex). */
+
+ DEBUGASSERT(conn->crefs == 0);
+
+ _can_semtake(&g_free_sem);
+
+ /* Remove the connection from the active list */
+
+ dq_rem(&conn->node, &g_active_can_connections);
+
+ /* Reset structure */
+
+ memset(conn, 0, sizeof(*conn));
+
+ /* Free the connection */
+
+ dq_addlast(&conn->node, &g_free_can_connections);
+ _can_semgive(&g_free_sem);
+}
+
+/****************************************************************************
+ * Name: can_nextconn()
+ *
+ * Description:
+ * Traverse the list of allocated NetLink connections
+ *
+ * Assumptions:
+ * This function is called from NetLink device logic.
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn)
+{
+ if (conn == NULL)
+ {
+ return (FAR struct can_conn_s *)g_active_can_connections.head;
+ }
+ else
+ {
+ return (FAR struct can_conn_s *)conn->node.flink;
+ }
+}
+
+/****************************************************************************
+ * Name: can_active
+ *
+ * Description:
+ * Find a connection structure that is the appropriate connection for the
+ * provided NetLink address
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+FAR struct can_conn_s *can_active(FAR struct sockaddr_can *addr)
+{
+ /* This function is used to handle routing of incoming messages to sockets
+ * connected to the address. There is no such use case for NetLink
+ * sockets.
+ */
+
+ return NULL;
+}
+
+#endif /* CONFIG_NET_CAN */
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
new file mode 100644
index 0000000..b7e3fe6
--- /dev/null
+++ b/net/can/can_sockif.c
@@ -0,0 +1,810 @@
+/****************************************************************************
+ * net/can/can_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 <sys/types.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#include <string.h>
+#include <poll.h>
+#include <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/net/net.h>
+
+#include "can/can.h"
+
+#ifdef CONFIG_NET_CAN
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int can_setup(FAR struct socket *psock, int protocol);
+static sockcaps_t can_sockcaps(FAR struct socket *psock);
+static void can_addref(FAR struct socket *psock);
+static int can_bind(FAR struct socket *psock,
+ FAR const struct sockaddr *addr, socklen_t addrlen);
+static int can_getsockname(FAR struct socket *psock,
+ FAR struct sockaddr *addr, FAR socklen_t *addrlen);
+static int can_getpeername(FAR struct socket *psock,
+ FAR struct sockaddr *addr, FAR socklen_t *addrlen);
+static int can_listen(FAR struct socket *psock, int backlog);
+static int can_connect(FAR struct socket *psock,
+ FAR const struct sockaddr *addr, socklen_t addrlen);
+static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen, FAR struct socket *newsock);
+static int can_poll(FAR struct socket *psock, FAR struct pollfd *fds,
+ bool setup);
+static ssize_t can_send(FAR struct socket *psock,
+ FAR const void *buf, size_t len, int flags);
+static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags, FAR const struct sockaddr *to,
+ socklen_t tolen);
+static ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf,
+ size_t len, int flags, FAR struct sockaddr *from,
+ FAR socklen_t *fromlen);
+static int can_close(FAR struct socket *psock);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct sock_intf_s g_can_sockif =
+{
+ can_setup, /* si_setup */
+ can_sockcaps, /* si_sockcaps */
+ can_addref, /* si_addref */
+ can_bind, /* si_bind */
+ can_getsockname, /* si_getsockname */
+ can_getpeername, /* si_getpeername */
+ can_listen, /* si_listen */
+ can_connect, /* si_connect */
+ can_accept, /* si_accept */
+ can_poll, /* si_poll */
+ can_send, /* si_send */
+ can_sendto, /* si_sendto */
+#ifdef CONFIG_NET_SENDFILE
+ NULL, /* si_sendfile */
+#endif
+ can_recvfrom, /* si_recvfrom */
+ can_close /* si_close */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: inet_setup
+ *
+ * Description:
+ * Called for socket() to verify that the provided socket type and
+ * protocol are usable by this address family. Perform any family-
+ * specific socket fields.
+ *
+ * Input Parameters:
+ * psock - A pointer to a user allocated socket structure to be
+ * initialized.
+ * protocol - NetLink socket protocol (see sys/socket.h)
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. Otherwise, a negated errno value is
+ * returned.
+ *
+ ****************************************************************************/
+
+static int can_setup(FAR struct socket *psock, int protocol)
+{
+ int domain = psock->s_domain;
+ int type = psock->s_type;
+
+ /* Verify that the protocol is supported */
+
+ DEBUGASSERT((unsigned int)protocol <= UINT8_MAX);
+
+ switch (protocol)
+ {
+ case CAN_RAW: /* RAW sockets */
+ case CAN_BCM: /* Broadcast Manager */
+ case CAN_TP16: /* VAG Transport Protocol v1.6 */
+ case CAN_TP20: /* VAG Transport Protocol v2.0 */
+ case CAN_MCNET: /* Bosch MCNet */
+ case CAN_ISOTP: /* ISO 15765-2 Transport Protocol */
+ case CAN_J1939: /* SAE J1939 */
+ break;
+
+ default:
+ return -EPROTONOSUPPORT;
+ }
+
+ /* Verify the socket type (domain should always be PF_CAN here) */
+
+ if (domain == PF_CAN && (type == SOCK_RAW || type == SOCK_DGRAM))
+ {
+ /* Allocate the NetLink socket connection structure and save it in the
+ * new socket instance.
+ */
+
+ FAR struct can_conn_s *conn = can_alloc();
+ if (conn == NULL)
+ {
+ /* Failed to reserve a connection structure */
+
+ return -ENOMEM;
+ }
+
+ /* Initialize the connection instance */
+
+ conn->protocol = (uint8_t)protocol;
+
+ /* Set the reference count on the connection structure. This
+ * reference count will be incremented only if the socket is
+ * dup'ed
+ */
+
+ conn->crefs = 1;
+
+ /* Attach the connection instance to the socket */
+
+ psock->s_conn = conn;
+ return OK;
+ }
+
+ return -EPROTONOSUPPORT;
+}
+
+/****************************************************************************
+ * Name: can_sockcaps
+ *
+ * Description:
+ * Return the bit encoded capabilities of this socket.
+ *
+ * Input Parameters:
+ * psock - Socket structure of the socket whose capabilities are being
+ * queried.
+ *
+ * Returned Value:
+ * The non-negative set of socket capabilities is returned.
+ *
+ ****************************************************************************/
+
+static sockcaps_t can_sockcaps(FAR struct socket *psock)
+{
+ /* Permit vfcntl to set socket to non-blocking */
+
+ return SOCKCAP_NONBLOCKING;
+}
+
+/****************************************************************************
+ * Name: can_addref
+ *
+ * Description:
+ * Increment the reference count on the underlying connection structure.
+ *
+ * Input Parameters:
+ * psock - Socket structure of the socket whose reference count will be
+ * incremented.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void can_addref(FAR struct socket *psock)
+{
+ FAR struct can_conn_s *conn;
+
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
+
+ conn = psock->s_conn;
+ DEBUGASSERT(conn->crefs > 0 && conn->crefs < 255);
+ conn->crefs++;
+}
+
+/****************************************************************************
+ * Name: can_bind
+ *
+ * Description:
+ * can_bind() gives the socket 'conn' the local address 'addr'. 'addr'
+ * is 'addrlen' bytes long. Traditionally, this is called "assigning a name
+ * to a socket." When a socket is created with socket, it exists in a name
+ * space (address family) but has no name assigned.
+ *
+ * Input Parameters:
+ * conn NetLink socket connection structure
+ * addr Socket local address
+ * addrlen Length of 'addr'
+ *
+ * Returned Value:
+ * 0 on success; -1 on error with errno set appropriately
+ *
+ * EACCES
+ * The address is protected, and the user is not the superuser.
+ * EADDRINUSE
+ * The given address is already in use.
+ * EINVAL
+ * The socket is already bound to an address.
+ * ENOTSOCK
+ * psock is a descriptor for a file, not a socket.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int can_bind(FAR struct socket *psock,
+ FAR const struct sockaddr *addr, socklen_t addrlen)
+{
+ FAR struct sockaddr_can *canaddr;
+ FAR struct can_conn_s *conn;
+
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
+ addrlen >= sizeof(struct sockaddr_can));
+
+ /* Save the address information in the connection structure */
+
+ canaddr = (FAR struct sockaddr_can *)addr;
+ conn = (FAR struct can_conn_s *)psock->s_conn;
+#warning Missing logic
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_getsockname
+ *
+ * Description:
+ * The getsockname() function retrieves the locally-bound name of the
+ * specified socket, stores this address in the sockaddr structure pointed
+ * to by the 'addr' argument, and stores the length of this address in the
+ * object pointed to by the 'addrlen' argument.
+ *
+ * If the actual length of the address is greater than the length of the
+ * supplied sockaddr structure, the stored address will be truncated.
+ *
+ * If the socket has not been bound to a local name, the value stored in
+ * the object pointed to by address is unspecified.
+ *
+ * Input Parameters:
+ * conn NetLink socket connection structure
+ * addr sockaddr structure to receive data [out]
+ * addrlen Length of sockaddr structure [in/out]
+ *
+ ****************************************************************************/
+
+static int can_getsockname(FAR struct socket *psock,
+ FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen)
+{
+ FAR struct sockaddr_can *canaddr;
+
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
+ addrlen != NULL && *addrlen >= sizeof(struct sockaddr_can));
+
+ /* Return the address information in the address structure */
+
+ canaddr = (FAR struct sockaddr_can *)addr;
+ memset(canaddr, 0, sizeof(struct sockaddr_can));
+
+ canaddr->can_family = AF_CAN;
+
+ if (_SS_ISBOUND(psock->s_flags))
+ {
+ FAR struct can_conn_s *conn;
+
+ conn = (FAR struct can_conn_s *)psock->s_conn;
+#warning Missing logic
+ }
+
+ *addrlen = sizeof(struct sockaddr_can);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: can_getpeername
+ *
+ * Description:
+ * The can_getpeername() function retrieves the remote-connected name
+ * of the specified packet socket, stores this address in the sockaddr
+ * structure pointed to by the 'addr' argument, and stores the length of
+ * this address in the object pointed to by the 'addrlen' argument.
+ *
+ * If the actual length of the address is greater than the length of the
+ * supplied sockaddr structure, the stored address will be truncated.
+ *
+ * If the socket has not been bound to a local name, the value stored in
+ * the object pointed to by address is unspecified.
+ *
+ * Parameters:
+ * psock Socket structure of the socket to be queried
+ * addr sockaddr structure to receive data [out]
+ * addrlen Length of sockaddr structure [in/out]
+ *
+ * Returned Value:
+ * On success, 0 is returned, the 'addr' argument points to the address
+ * of the socket, and the 'addrlen' argument points to the length of the
+ * address. Otherwise, a negated errno value is returned. See
+ * getpeername() for the list of appropriate error numbers.
+ *
+ ****************************************************************************/
+
+static int can_getpeername(FAR struct socket *psock,
+ FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen)
+{
+#warning Missing logic
+ return -EOPNOTSUPP; /* Or maybe return -EAFNOSUPPORT; */
+}
+
+/****************************************************************************
+ * Name: can_listen
+ *
+ * Description:
+ * To accept connections, a socket is first created with psock_socket(), a
+ * willingness to accept incoming connections and a queue limit for
+ * incoming connections are specified with psock_listen(), and then the
+ * connections are accepted with psock_accept(). For the case of AFINET
+ * and AFINET6 sockets, psock_listen() calls this function. The
+ * psock_listen() call applies only to sockets of type SOCK_STREAM or
+ * SOCK_SEQPACKET.
+ *
+ * Input Parameters:
+ * psock Reference to an internal, bound socket structure.
+ * backlog The maximum length the queue of pending connections may grow.
+ * If a connection request arrives with the queue full, the client
+ * may receive an error with an indication of ECONNREFUSED or,
+ * if the underlying protocol supports retransmission, the request
+ * may be ignored so that retries succeed.
+ *
+ * Returned Value:
+ * On success, zero is returned. On error, a negated errno value is
+ * returned. See list() for the set of appropriate error values.
+ *
+ ****************************************************************************/
+
+static int can_listen(FAR struct socket *psock, int backlog)
+{
+#warning Missing logic
+ return -EOPNOTSUPP;
+}
+
+/****************************************************************************
+ * Name: can_connect
+ *
+ * Description:
+ * Perform a can connection
+ *
+ * Input Parameters:
+ * psock A reference to the socket structure of the socket to be connected
+ * addr The address of the remote server to connect to
+ * addrlen Length of address buffer
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int can_connect(FAR struct socket *psock,
+ FAR const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+#warning Missing logic
+ return -EOPNOTSUPP;
+}
+
+/****************************************************************************
+ * Name: can_accept
+ *
+ * Description:
+ * The can_accept function is used with connection-based socket
+ * types (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
+ * connection request on the queue of pending connections, creates a new
+ * connected socket with mostly the same properties as 'sockfd', and
+ * allocates a new socket descriptor for the socket, which is returned. The
+ * newly created socket is no longer in the listening state. The original
+ * socket 'sockfd' is unaffected by this call. Per file descriptor flags
+ * are not inherited across an inet_accept.
+ *
+ * The 'sockfd' argument is a socket descriptor that has been created with
+ * socket(), bound to a local address with bind(), and is listening for
+ * connections after a call to listen().
+ *
+ * On return, the 'addr' structure is filled in with the address of the
+ * connecting entity. The 'addrlen' argument initially contains the size
+ * of the structure pointed to by 'addr'; on return it will contain the
+ * actual length of the address returned.
+ *
+ * If no pending connections are present on the queue, and the socket is
+ * not marked as non-blocking, inet_accept blocks the caller until a
+ * connection is present. If the socket is marked non-blocking and no
+ * pending connections are present on the queue, inet_accept returns
+ * EAGAIN.
+ *
+ * Input Parameters:
+ * psock Reference to the listening socket structure
+ * addr Receives the address of the connecting client
+ * addrlen Input: Allocated size of 'addr'
+ * Return: Actual size returned size of 'addr'
+ * newsock Location to return the accepted socket information.
+ *
+ * Returned Value:
+ * Returns 0 (OK) on success. On failure, it returns a negated errno
+ * value. See accept() for a description of the appropriate error value.
+ *
+ * Assumptions:
+ * The network is locked.
+ *
+ ****************************************************************************/
+
+static int can_accept(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen, FAR struct socket *newsock)
+{
+#warning Missing logic
+ return -EOPNOTSUPP;
+}
+
+/****************************************************************************
+ * Name: can_poll
+ *
+ * Description:
+ * The standard poll() operation redirects operations on socket descriptors
+ * to this function.
+ *
+ * POLLUP: Will never be reported
+ * POLLERR: Reported in the event of any failure.
+ * POLLOUT: Always reported if requested.
+ * POLLIN: Reported if requested but only when pending response data is
+ * available
+ *
+ * Input Parameters:
+ * psock - An instance of the internal socket structure.
+ * fds - The structure describing the events to be monitored.
+ * setup - true: Setup up the poll; false: Tear down the poll
+ *
+ * Returned Value:
+ * 0: Success; Negated errno on failure
+ *
+ ****************************************************************************/
+
+static int can_poll(FAR struct socket *psock, FAR struct pollfd *fds,
+ bool setup)
+{
+ FAR struct can_conn_s *conn;
+ int ret;
+
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL);
+ conn = (FAR struct can_conn_s *)psock->s_conn;
+
+ /* Check if we are setting up or tearing down the poll */
+
+ if (setup)
+ {
+ /* If POLLOUT is selected, return immediately (maybe) */
+
+ pollevent_t revents = POLLOUT;
+
+ /* If POLLIN is selected and a response is available, return
+ * immediately if POLLIN and/or POLLIN are included in the
+ * requested event set.
+ */
+
+ net_lock();
+
+#warning Missing logic
+
+ revents &= fds->events;
+ if (revents != 0)
+ {
+ fds->revents = revents;
+ nxsem_post(fds->sem);
+ net_unlock();
+ return OK;
+ }
+
+ /* Set up to be notified when a response is available if POLLIN is
+ * requested.
+ */
+
+ if ((fds->events & POLLIN) != 0)
+ {
+ /* Some limitations: There can be only a single outstanding POLLIN
+ * on the CAN connection.
+ */
+
+ if (conn->pollsem != NULL || conn->pollevent != NULL)
+ {
+ nerr("ERROR: Multiple polls() on socket not supported.\n");
+ net_unlock();
+ return -EBUSY;
+ }
+
+ /* Set up the notification */
+
+ conn->pollsem = fds->sem;
+ conn->pollevent = &fds->revents;
+
+#warning Missing logic
+
+ if (ret < 0)
+ {
+ /* Failed to set up notification */
+
+ conn->pollsem = NULL;
+ conn->pollevent = NULL;
+ }
+ else
+ {
+ /* Setup to receive a notification when CAN data is available */
+
+#warning Missing logic
+
+ ret = OK;
+ }
+ }
+
+ /* Set up to be notified when we are able to send CAN data without
+ * waiting.
+ */
+
+ else if ((fds->events & POLLOUT) != 0)
+ {
+ }
+ else
+ {
+ /* There will not be any wakeups coming? Probably an error? */
+
+ ret = OK;
+ }
+
+ net_unlock();
+ }
+ else
+ {
+ /* Cancel any response notifications */
+
+ conn->pollsem = NULL;
+ conn->pollevent = NULL;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: can_send
+ *
+ * Description:
+ * The can_send() call may be used only when the socket is in
+ * a connected state (so that the intended recipient is known).
+ *
+ * Input Parameters:
+ * psock - An instance of the internal socket structure.
+ * buf - Data to send
+ * len - Length of data to send
+ * flags - Send flags (ignored)
+ *
+ * Returned Value:
+ * On success, returns the number of characters sent. On error, a negated
+ * errno value is returned (see send() for the list of appropriate error
+ * values.
+ *
+ ****************************************************************************/
+
+static ssize_t can_send(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags)
+{
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
+
+ /* The socket must be connected in order to use send */
+
+ if (_SS_ISBOUND(psock->s_flags))
+ {
+ FAR struct can_conn_s *conn;
+ struct sockaddr_can canaddr;
+
+ /* Get the underlying connection structure */
+
+ conn = (FAR struct can_conn_s *)psock->s_conn;
+
+ /* Format the address */
+
+ canaddr.can_family = AF_CAN;
+#warning Missing logic
+
+ /* Then let sendto() perform the actual send operation */
+
+ return can_sendto(psock, buf, len, flags,
+ (FAR const struct sockaddr *)&canaddr,
+ sizeof(struct sockaddr_can));
+ }
+
+ /* EDESTADDRREQ. Signifies that the socket is not connection-mode and no
+ * peer address is set.
+ */
+
+ return -EDESTADDRREQ;
+}
+
+/****************************************************************************
+ * Name: can_sendto
+ *
+ * Description:
+ * If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
+ * socket, the parameters to and 'tolen' are ignored (and the error EISCONN
+ * may be returned when they are not NULL and 0), and the error ENOTCONN is
+ * returned when the socket was not actually connected.
+ *
+ * Input Parameters:
+ * psock A reference to the socket structure of the socket to be connected
+ * buf Data to send
+ * len Length of data to send
+ * flags Send flags (ignored)
+ * to Address of recipient
+ * tolen The length of the address structure
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags,
+ FAR const struct sockaddr *to, socklen_t tolen)
+{
+ FAR struct can_conn_s *conn;
+ int ret;
+
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL &&
+ to != NULL && tolen >= sizeof(struct sockaddr_can));
+
+ conn = (FAR struct can_conn_s *)psock->s_conn;
+#warning Missing logic
+
+ switch (conn->protocol)
+ {
+#warning Missing logic
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: can_recvfrom
+ *
+ * Description:
+ * recvfrom() receives messages from a socket, and may be used to receive
+ * data on a socket whether or not it is connection-oriented.
+ *
+ * If from is not NULL, and the underlying protocol provides the source
+ * address, this source address is filled in. The argument 'fromlen'
+ * initialized to the size of the buffer associated with from, and modified
+ * on return to indicate the actual size of the address stored there.
+ *
+ * Input Parameters:
+ * psock A pointer to a NuttX-specific, internal socket structure
+ * buf Buffer to receive data
+ * len Length of buffer
+ * flags Receive flags (ignored)
+ * from Address of source (may be NULL)
+ * fromlen The length of the address structure
+ *
+ ****************************************************************************/
+
+static ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf,
+ size_t len, int flags,
+ FAR struct sockaddr *from,
+ FAR socklen_t *fromlen)
+{
+ FAR struct can_conn_s *conn;
+ int ret;
+
+ DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
+ DEBUGASSERT(from == NULL ||
+ (fromlen != NULL && *fromlen >= sizeof(struct sockaddr_can)));
+
+ conn = (FAR struct can_conn_s *)psock->s_conn;
+#warning Missing logic
+
+ switch (conn->protocol)
+ {
+#warning Missing logic
+
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: can_close
+ *
+ * Description:
+ * Performs the close operation on a NetLink socket instance
+ *
+ * Input Parameters:
+ * psock Socket instance
+ *
+ * Returned Value:
+ * 0 on success; -1 on error with errno set appropriately.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int can_close(FAR struct socket *psock)
+{
+ FAR struct can_conn_s *conn = psock->s_conn;
+ int ret = OK;
+
+ /* Perform some pre-close operations for the CAN socket type. */
+
+ /* Is this the last reference to the connection structure (there
+ * could be more if the socket was dup'ed).
+ */
+
+ if (conn->crefs <= 1)
+ {
+ /* Yes... inform user-space daemon of socket close. */
+
+#warning Missing logic
+
+ /* Free the connection structure */
+
+ conn->crefs = 0;
+ can_free(psock->s_conn);
+
+ if (ret < 0)
+ {
+ /* Return with error code, but free resources. */
+
+ nerr("ERROR: can_close failed: %d\n", ret);
+ return ret;
+ }
+ }
+ else
+ {
+ /* No.. Just decrement the reference count */
+
+ conn->crefs--;
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NET_CAN */
diff --git a/net/net_initialize.c b/net/net_initialize.c
index eb82777..bedc4e3 100644
--- a/net/net_initialize.c
+++ b/net/net_initialize.c
@@ -59,6 +59,7 @@
#include "bluetooth/bluetooth.h"
#include "ieee802154/ieee802154.h"
#include "local/local.h"
+#include "can/can.h"
#include "netlink/netlink.h"
#include "igmp/igmp.h"
#include "route/route.h"
@@ -158,6 +159,12 @@ void net_initialize(void)
local_initialize();
#endif
+#ifdef CONFIG_NET_CAN
+ /* Initialize SocketCAN support */
+
+ can_initialize();
+#endif
+
#ifdef CONFIG_NET_NETLINK
/* Initialize the Netlink IPC support */
diff --git a/net/socket/net_sockif.c b/net/socket/net_sockif.c
index 01e8368..cc956d8 100644
--- a/net/socket/net_sockif.c
+++ b/net/socket/net_sockif.c
@@ -47,6 +47,7 @@
#include "inet/inet.h"
#include "local/local.h"
+#include "can/can.h"
#include "netlink/netlink.h"
#include "pkt/pkt.h"
#include "bluetooth/bluetooth.h"
@@ -104,6 +105,12 @@ net_sockif(sa_family_t family, int type, int protocol)
break;
#endif
+#ifdef CONFIG_NET_CAN
+ case PF_CAN:
+ sockif = &g_can_sockif;
+ break;
+#endif
+
#ifdef CONFIG_NET_NETLINK
case PF_NETLINK:
sockif = &g_netlink_sockif;