nuttx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gn...@apache.org
Subject [incubator-nuttx] 03/31: net/: Add WIP initial framework for SocketCAN sockets.
Date Sun, 12 Apr 2020 17:54:35 GMT
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 f20b6474d56e321464c4266a39ae02847cb79bd5
Author: Gregory Nutt <gnutt@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 2890aaf..066d061 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -66,6 +66,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;


Mime
View raw message