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: