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: