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 ff8e51327ac920da3f98c4ee01afb9549b590a15
Author: Peter van der Perk <peter.vanderp...@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:

Reply via email to