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:29 UTC
[incubator-nuttx] 11/31: Added CAN_RAW_FD_FRAMES sockopt support
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 1fa53edb62ae731af44ef7677f7b422fad547d95
Author: Peter van der Perk <pe...@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;