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 88d67a95741969b64516cf409688c1e2de236e49 Author: Peter van der Perk <peter.vanderp...@nxp.com> AuthorDate: Wed Feb 26 13:36:24 2020 +0100 Added CAN_RAW_FD_FRAMES sockopt support Also CAN FD is disabled on startup, which is default behaviour for SocketCAN --- net/can/can.h | 10 ++++++++++ net/can/can_conn.c | 3 +++ net/can/can_getsockopt.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ net/can/can_recvfrom.c | 28 +++++++++++++++++++++++---- net/can/can_send.c | 50 ++++++++++++++++++++++++++++++------------------ net/can/can_setsockopt.c | 21 +++++++++++++++++--- net/socket/getsockopt.c | 4 ++-- net/socket/setsockopt.c | 6 ++++++ 8 files changed, 142 insertions(+), 28 deletions(-) diff --git a/net/can/can.h b/net/can/can.h index 67c8d6f..5992deb 100644 --- a/net/can/can.h +++ b/net/can/can.h @@ -104,6 +104,16 @@ struct can_conn_s */ struct can_poll_s pollinfo[4]; /* FIXME make dynamic */ + +#ifdef CONFIG_NET_CANPROTO_OPTIONS + int32_t loopback; + int32_t recv_own_msgs; + int32_t fd_frames; + + /* TODO add filter support */ +#endif + + }; /**************************************************************************** diff --git a/net/can/can_conn.c b/net/can/can_conn.c index 4969f6d..21622b5 100644 --- a/net/can/can_conn.c +++ b/net/can/can_conn.c @@ -138,6 +138,9 @@ FAR struct can_conn_s *can_alloc(void) /* Make sure that the connection is marked as uninitialized */ memset(conn, 0, sizeof(*conn)); + + /* FIXME SocketCAN default behavior enables loopback */ + /* Enqueue the connection into the active list */ diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c index 1fe8218..91720ad 100644 --- a/net/can/can_getsockopt.c +++ b/net/can/can_getsockopt.c @@ -114,12 +114,60 @@ int can_getsockopt(FAR struct socket *psock, int option, break; case CAN_RAW_LOOPBACK: + if (*value_len < sizeof(conn->loopback)) + { + /* REVISIT: POSIX says that we should truncate the value if it + * is larger than value_len. That just doesn't make sense + * to me in this case. + */ + + ret = -EINVAL; + } + else + { + FAR int *loopback = (FAR int32_t *)value; + *loopback = conn->loopback; + *value_len = sizeof(conn->loopback); + ret = OK; + } break; case CAN_RAW_RECV_OWN_MSGS: + if (*value_len < sizeof(conn->recv_own_msgs)) + { + /* REVISIT: POSIX says that we should truncate the value if it + * is larger than value_len. That just doesn't make sense + * to me in this case. + */ + + ret = -EINVAL; + } + else + { + FAR int *recv_own_msgs = (FAR int32_t *)value; + *recv_own_msgs = conn->recv_own_msgs; + *value_len = sizeof(conn->recv_own_msgs); + ret = OK; + } break; case CAN_RAW_FD_FRAMES: + if (*value_len < sizeof(conn->fd_frames)) + { + /* REVISIT: POSIX says that we should truncate the value if it + * is larger than value_len. That just doesn't make sense + * to me in this case. + */ + + ret = -EINVAL; + } + else + { + FAR int *fd_frames = (FAR int32_t *)value; + *fd_frames = conn->fd_frames; + *value_len = sizeof(conn->fd_frames); + ret = OK; + } break; case CAN_RAW_JOIN_FILTERS: diff --git a/net/can/can_recvfrom.c b/net/can/can_recvfrom.c index d2f71a6..f83d07c 100644 --- a/net/can/can_recvfrom.c +++ b/net/can/can_recvfrom.c @@ -276,6 +276,16 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) IOBUSER_NET_CAN_READAHEAD); } + /* do not pass frames with DLC > 8 to a legacy socket */ + if (!conn->fd_frames) + { + struct canfd_frame *cfd = (struct canfd_frame *)pstate->pr_buffer; + if (cfd->len > CAN_MAX_DLEN) + { + return 0; + } + } + return recvlen; } @@ -287,6 +297,7 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev, FAR void *pvpriv, uint16_t flags) { struct can_recvfrom_s *pstate = (struct can_recvfrom_s *)pvpriv; + struct can_conn_s *conn = (struct can_conn_s *)pstate->pr_sock->s_conn; /* 'priv' might be null in some race conditions (?) */ @@ -296,6 +307,18 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev, if ((flags & CAN_NEWDATA) != 0) { + /* 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; + if (cfd->len > CAN_MAX_DLEN) + { + /* DO WE NEED TO CLEAR FLAGS?? */ + flags &= ~CAN_NEWDATA; + return flags; + } + } + /* Copy the packet */ can_newdata(dev, pstate); @@ -355,10 +378,7 @@ static ssize_t can_recvfrom_result(int result, if (pstate->pr_result < 0) { - /* This might return EAGAIN on a timeout or ENOTCONN on loss of - * connection (CAN only) - */ - + /* This might return EAGAIN on a timeout */ return pstate->pr_result; } diff --git a/net/can/can_send.c b/net/can/can_send.c index 6b7a609..1d8677d 100644 --- a/net/can/can_send.c +++ b/net/can/can_send.c @@ -184,6 +184,21 @@ ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf, { return -ENODEV; } + + if(conn->fd_frames) + { + if(len != CANFD_MTU && len != CAN_MTU) + { + return -EINVAL; + } + } + else + { + if(len != CAN_MTU) + { + return -EINVAL; + } + } /* Perform the send operation */ @@ -205,33 +220,30 @@ ssize_t psock_can_send(FAR struct socket *psock, FAR const void *buf, state.snd_buflen = len; /* Number of bytes to send */ state.snd_buffer = buf; /* Buffer to send from */ - if (len > 0) - { - /* Allocate resource to receive a callback */ + /* Allocate resource to receive a callback */ - state.snd_cb = can_callback_alloc(dev, conn); - if (state.snd_cb) - { - /* Set up the callback in the connection */ + state.snd_cb = can_callback_alloc(dev, conn); + if (state.snd_cb) + { + /* Set up the callback in the connection */ - state.snd_cb->flags = CAN_POLL; - state.snd_cb->priv = (FAR void *)&state; - state.snd_cb->event = psock_send_eventhandler; + state.snd_cb->flags = CAN_POLL; + state.snd_cb->priv = (FAR void *)&state; + state.snd_cb->event = psock_send_eventhandler; - /* Notify the device driver that new TX data is available. */ + /* Notify the device driver that new TX data is available. */ - netdev_txnotify_dev(dev); + netdev_txnotify_dev(dev); - /* Wait for the send to complete or an error to occur. - * net_lockedwait will also terminate if a signal is received. - */ + /* Wait for the send to complete or an error to occur. + * net_lockedwait will also terminate if a signal is received. + */ - ret = net_lockedwait(&state.snd_sem); + ret = net_lockedwait(&state.snd_sem); - /* Make sure that no further events are processed */ + /* Make sure that no further events are processed */ - can_callback_free(dev, conn, state.snd_cb); - } + can_callback_free(dev, conn, state.snd_cb); } nxsem_destroy(&state.snd_sem); diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c index 2d117a8..3bad6e0 100644 --- a/net/can/can_setsockopt.c +++ b/net/can/can_setsockopt.c @@ -108,13 +108,28 @@ int can_setsockopt(FAR struct socket *psock, int option, break; case CAN_RAW_LOOPBACK: - break; + if (value_len != sizeof(conn->loopback)) + return -EINVAL; + + conn->loopback = *(FAR int32_t *)value; + + break; case CAN_RAW_RECV_OWN_MSGS: - break; + if (value_len != sizeof(conn->recv_own_msgs)) + return -EINVAL; + + conn->recv_own_msgs = *(FAR int32_t *)value; + + break; case CAN_RAW_FD_FRAMES: - break; + if (value_len != sizeof(conn->fd_frames)) + return -EINVAL; + + conn->fd_frames = *(FAR int32_t *)value; + + break; case CAN_RAW_JOIN_FILTERS: break; diff --git a/net/socket/getsockopt.c b/net/socket/getsockopt.c index 6d71106..fa58e6d 100644 --- a/net/socket/getsockopt.c +++ b/net/socket/getsockopt.c @@ -371,8 +371,8 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option, break; #endif - case SOL_CAN_RAW: -#ifdef CONFIG_NET_TCPPROTO_OPTIONS + case SOL_CAN_RAW:/* CAN protocol socket options (see include/netpacket/can.h) */ +#ifdef CONFIG_NET_CANPROTO_OPTIONS ret = can_getsockopt(psock, option, value, value_len); #endif break; diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c index 211a1df..46e1b6e 100644 --- a/net/socket/setsockopt.c +++ b/net/socket/setsockopt.c @@ -399,6 +399,12 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option, break; #endif +#ifdef CONFIG_NET_CAN + case SOL_CAN_RAW: /* CAN protocol socket options (see include/netpacket/can.h) */ + ret = can_setsockopt(psock, option, value, value_len); + break; +#endif + default: /* The provided level is invalid */ ret = -EINVAL; break;