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:33 UTC

[incubator-nuttx] 15/31: Added functional support for CAN_RAW_FILTER sockopt

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 1f32cf314ade6950b8066b58375f9648ed302d0e
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Mon Mar 9 12:47:26 2020 +0100

    Added functional support for CAN_RAW_FILTER sockopt
---
 include/nuttx/can.h      |  1 -
 net/can/Kconfig          |  7 +++++++
 net/can/can.h            |  2 ++
 net/can/can_conn.c       | 17 +++++++++++++++++
 net/can/can_getsockopt.c | 27 ++++++++++++++++++++-------
 net/can/can_input.c      |  2 +-
 net/can/can_recvfrom.c   | 47 ++++++++++++++++++++++++++++++++++++++---------
 net/can/can_setsockopt.c | 22 +++++++++++++++++-----
 8 files changed, 102 insertions(+), 23 deletions(-)

diff --git a/include/nuttx/can.h b/include/nuttx/can.h
index 7a66a65..c681b32 100644
--- a/include/nuttx/can.h
+++ b/include/nuttx/can.h
@@ -214,7 +214,6 @@
 #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
 
 #define CAN_INV_FILTER     0x20000000U /* to be set in can_filter.can_id */
-#define CAN_RAW_FILTER_MAX 512         /* maximum number of can_filter set via setsockopt() */
 
 /************************************************************************************
  * Public Types
diff --git a/net/can/Kconfig b/net/can/Kconfig
index d5b6dbd..3b2e450 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -31,6 +31,13 @@ config NET_CAN_SOCK_OPTS
 	---help---
 		Enable support for the CAN socket options
 		
+config NET_CAN_RAW_FILTER_MAX
+	int "CAN_RAW_FILTER max filter count"
+	default 32
+	depends on NET_CAN_SOCK_OPTS
+	---help---
+		Maximum number of CAN_RAW filters that can be set per CAN connection.
+		
 config NET_CAN_NOTIFIER
 	bool "Support CAN notifications"
 	default n
diff --git a/net/can/can.h b/net/can/can.h
index 5992deb..e5d45f0 100644
--- a/net/can/can.h
+++ b/net/can/can.h
@@ -109,6 +109,8 @@ struct can_conn_s
   int32_t loopback;
   int32_t recv_own_msgs;
   int32_t fd_frames;
+  struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX];
+  int32_t filter_count;
   
   /* TODO add filter support */
 #endif
diff --git a/net/can/can_conn.c b/net/can/can_conn.c
index 21622b5..74f2d9b 100644
--- a/net/can/can_conn.c
+++ b/net/can/can_conn.c
@@ -142,6 +142,23 @@ FAR struct can_conn_s *can_alloc(void)
       /* FIXME SocketCAN default behavior enables loopback */
       
 
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+      /* By default the filter is configured to catch all,
+       * this is done in commented filter code below:
+       *
+       * struct can_filter_t catchall_filter;
+       * filter.can_id = 0;
+       * filter.can_mask = 0;
+       * conn->filters[0] = catchall_filter;
+       *
+       * However memset already sets the filter to 0
+       * therefore we only have to set the filter count to 1
+       */
+
+      conn->filter_count = 1;
+#endif
+
+
       /* Enqueue the connection into the active list */
 
       dq_addlast(&conn->node, &g_active_can_connections);
diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c
index 91720ad..e4149b6 100644
--- a/net/can/can_getsockopt.c
+++ b/net/can/can_getsockopt.c
@@ -98,16 +98,29 @@ int can_getsockopt(FAR struct socket *psock, int option,
           {
             ret = -EINVAL;
           }
-
-        if (value_len > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
+        else if (*value_len > CONFIG_NET_CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
           {
             ret = -EINVAL;
           }
-
-        count = *value_len / sizeof(struct can_filter);
-
-        /* FIXME pass filter to driver */
-
+        else
+          {
+            int count = conn->filter_count;
+
+        	if (*value_len < count * sizeof(struct can_filter))
+              {
+                count = *value_len / sizeof(struct can_filter);
+              }
+        	else
+        	  {
+        	    *value_len = count * sizeof(struct can_filter);
+        	  }
+
+            for(int i = 0; i < count; i++)
+              {
+            	((struct can_filter *)value)[i] = conn->filters[i];
+              }
+            ret = OK;
+          }
         break;
 
       case CAN_RAW_ERR_FILTER:
diff --git a/net/can/can_input.c b/net/can/can_input.c
index 30e2507..52d6c50 100644
--- a/net/can/can_input.c
+++ b/net/can/can_input.c
@@ -64,7 +64,7 @@ int can_input(struct net_driver_s *dev)
   FAR struct can_conn_s *conn;
   int ret = OK;
 
-  conn = can_nextconn(NULL); /* FIXME  */
+  conn = can_nextconn(NULL); /* FIXME Support for multiple sockets??? */
   if (conn)
     {
       uint16_t flags;
diff --git a/net/can/can_recvfrom.c b/net/can/can_recvfrom.c
index c23af93..06b133c 100644
--- a/net/can/can_recvfrom.c
+++ b/net/can/can_recvfrom.c
@@ -294,6 +294,33 @@ static inline int can_readahead(struct can_recvfrom_s *pstate)
   return 0;
 }
 
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+static int can_recv_filter(struct can_conn_s *conn, canid_t id)
+{
+  for(int i = 0; i < conn->filter_count; i++)
+    {
+	  if (conn->filters[i].can_id & CAN_INV_FILTER)
+	    {
+		  if((id & conn->filters[i].can_mask) !=
+				  ((conn->filters[i].can_id & ~CAN_INV_FILTER)
+						  & conn->filters[i].can_mask))
+		    {
+			  return 1;
+		    }
+	    }
+	  else
+	    {
+		  if((id & conn->filters[i].can_mask) ==
+				  (conn->filters[i].can_id & conn->filters[i].can_mask))
+		    {
+			  return 1;
+		    }
+	    }
+    }
+  return 0;
+}
+#endif
+
 static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
                                           FAR void *pvconn,
                                           FAR void *pvpriv, uint16_t flags)
@@ -305,14 +332,22 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
 
   if (pstate)
     {
-      /* If a new packet is available, then complete the read action. */
-
       if ((flags & CAN_NEWDATA) != 0)
         {
+    	  /* If a new packet is available, check receive filters
+    	   * when is valid then complete the read action. */
+#ifdef CONFIG_NET_CANPROTO_OPTIONS
+    	  if(can_recv_filter(conn,(canid_t)*dev->d_appdata) == 0)
+    	    {
+    		  flags &= ~CAN_NEWDATA;
+    	  	  return flags;
+    		}
+#endif
+
     	  /* do not pass frames with DLC > 8 to a legacy socket */
     	  if (!conn->fd_frames)
     	    {
-    		  struct canfd_frame *cfd = (struct canfd_frame *)dev->d_appdata;
+    		  struct canfd_frame *cfd = (struct canfd_frame*)dev->d_appdata;
     	      if (cfd->len > CAN_MAX_DLEN)
     	      {
     	    	/* DO WE NEED TO CLEAR FLAGS?? */
@@ -333,12 +368,6 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev,
           pstate->pr_cb->priv    = NULL;
           pstate->pr_cb->event   = NULL;
 
-#if 0
-          /* Save the sender's address in the caller's 'from' location */
-
-          pkt_recvfrom_sender(dev, pstate);
-#endif
-
           /* indicate that the data has been consumed */
 
           flags &= ~CAN_NEWDATA;
diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c
index 3bad6e0..659d84b 100644
--- a/net/can/can_setsockopt.c
+++ b/net/can/can_setsockopt.c
@@ -88,20 +88,32 @@ int can_setsockopt(FAR struct socket *psock, int option,
   switch (option)
     {
       case CAN_RAW_FILTER:
-        if (value_len % sizeof(struct can_filter) != 0)
+    	if (value_len == 0)
+    	  {
+    		conn->filter_count = 0;
+    	    ret = OK;
+    	  }
+    	else if (value_len % sizeof(struct can_filter) != 0)
           {
             ret = -EINVAL;
           }
-
-        if (value_len > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
+        else if (value_len > CONFIG_NET_CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
           {
             ret = -EINVAL;
           }
+        else
+          {
+		    count = value_len / sizeof(struct can_filter);
 
-        count = value_len / sizeof(struct can_filter);
+		    for(int i = 0; i < count; i++)
+		      {
+				conn->filters[i] = ((struct can_filter *)value)[i];
+		      }
 
-        /* FIXME pass filter to driver */
+		    conn->filter_count = count;
 
+            ret = OK;
+          }
         break;
 
       case CAN_RAW_ERR_FILTER: