diff --git a/net/can/can.h b/net/can/can.h index 534f08fafcc13..df3d15c239151 100644 --- a/net/can/can.h +++ b/net/can/can.h @@ -104,22 +104,11 @@ 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; -# ifdef CONFIG_NET_CAN_CANFD - int32_t fd_frames; -# endif struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX]; int32_t filter_count; # ifdef CONFIG_NET_CAN_ERRORS can_err_mask_t err_mask; # endif -# ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE - int32_t tx_deadline; -# endif -#endif -#ifdef CONFIG_NET_TIMESTAMP - int32_t timestamp; /* Socket timestamp enabled/disabled */ #endif }; diff --git a/net/can/can_callback.c b/net/can/can_callback.c index 03e8af828360f..85db2783d2142 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -140,7 +140,7 @@ uint16_t can_callback(FAR struct net_driver_s *dev, * create timestamp and copy to iob */ - if (conn->timestamp) + if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP)) { struct timeval tv; FAR struct timespec *ts = (FAR struct timespec *)&tv; diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c index 8360a56cb45cd..6d9f66c019dc4 100644 --- a/net/can/can_getsockopt.c +++ b/net/can/can_getsockopt.c @@ -83,19 +83,6 @@ int can_getsockopt(FAR struct socket *psock, int level, int option, DEBUGASSERT(value != NULL && value_len != NULL); conn = psock->s_conn; -#ifdef CONFIG_NET_TIMESTAMP - if (level == SOL_SOCKET && option == SO_TIMESTAMP) - { - if (*value_len != sizeof(int32_t)) - { - return -EINVAL; - } - - *(FAR int32_t *)value = conn->timestamp; - return OK; - } -#endif - if (level != SOL_CAN_RAW) { return -ENOPROTOOPT; @@ -140,8 +127,8 @@ int can_getsockopt(FAR struct socket *psock, int level, int option, } break; - case CAN_RAW_ERR_FILTER: #ifdef CONFIG_NET_CAN_ERRORS + case CAN_RAW_ERR_FILTER: if (*value_len < sizeof(can_err_mask_t)) { return -EINVAL; @@ -152,87 +139,35 @@ int can_getsockopt(FAR struct socket *psock, int level, int option, *mask = conn->err_mask; *value_len = sizeof(can_err_mask_t); } -#endif break; +#endif 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 int32_t *loopback = (FAR int32_t *)value; - *loopback = conn->loopback; - *value_len = sizeof(conn->loopback); - } - 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 int32_t *recv_own_msgs = (FAR int32_t *)value; - *recv_own_msgs = conn->recv_own_msgs; - *value_len = sizeof(conn->recv_own_msgs); - } - break; - #ifdef CONFIG_NET_CAN_CANFD 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 int32_t *fd_frames = (FAR int32_t *)value; - *fd_frames = conn->fd_frames; - *value_len = sizeof(conn->fd_frames); - } - break; #endif - - case CAN_RAW_JOIN_FILTERS: - break; - #ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE case CAN_RAW_TX_DEADLINE: - if (*value_len < sizeof(conn->tx_deadline)) - { - /* 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. - */ +#endif + /* Verify that option is the size of an 'int'. Should also check + * that 'value' is properly aligned for an 'int' + */ - ret = -EINVAL; - } - else + if (*value_len < sizeof(int)) { - FAR int32_t *tx_deadline = (FAR int32_t *)value; - *tx_deadline = conn->tx_deadline; - *value_len = sizeof(conn->tx_deadline); - } - break; -#endif + return -EINVAL; + } + + /* Sample the current options. This is atomic operation and so + * should not require any special steps for thread safety. We + * this outside of the macro because you can never be sure what + * a macro will do. + */ + + *(FAR int *)value = _SO_GETOPT(conn->sconn.s_options, option); + *value_len = sizeof(int); + break; #if CONFIG_NET_RECV_BUFSIZE > 0 case SO_RCVBUF: diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c index fdfa6be80fac3..2226849e691be 100644 --- a/net/can/can_recvmsg.c +++ b/net/can/can_recvmsg.c @@ -131,9 +131,10 @@ static size_t can_recvfrom_newdata(FAR struct net_driver_s *dev, { unsigned int offset; size_t recvlen; - #ifdef CONFIG_NET_TIMESTAMP - if (pstate->pr_conn->timestamp && + FAR struct can_conn_s *conn = pstate->pr_conn; + + if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && pstate->pr_msglen == sizeof(struct timeval)) { iob_copyout(pstate->pr_msgbuf, dev->d_iob, sizeof(struct timeval), @@ -266,7 +267,8 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) #endif #ifdef CONFIG_NET_TIMESTAMP - if (conn->timestamp && pstate->pr_msglen == sizeof(struct timeval)) + if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && + pstate->pr_msglen == sizeof(struct timeval)) { iob_copyout(pstate->pr_msgbuf, iob, sizeof(struct timeval), -CONFIG_NET_LL_GUARDSIZE); @@ -313,7 +315,7 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) /* do not pass frames with DLC > 8 to a legacy socket */ #if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) - if (!conn->fd_frames) + if (!_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) #endif { if (recvlen > sizeof(struct can_frame)) @@ -398,14 +400,15 @@ static uint16_t can_recvfrom_eventhandler(FAR struct net_driver_s *dev, /* do not pass frames with DLC > 8 to a legacy socket */ #if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) - if (!conn->fd_frames) + if (!_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) #endif { #ifdef CONFIG_NET_TIMESTAMP - if ((conn->timestamp && (dev->d_len > - sizeof(struct can_frame) + sizeof(struct timeval))) - || (!conn->timestamp && (dev->d_len > - sizeof(struct can_frame)))) + if ((_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && + dev->d_len > sizeof(struct can_frame) + + sizeof(struct timeval)) || + (!_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP) && + dev->d_len > sizeof(struct can_frame))) #else if (dev->d_len > sizeof(struct can_frame)) #endif @@ -534,7 +537,7 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, state.pr_buffer = msg->msg_iov->iov_base; #ifdef CONFIG_NET_TIMESTAMP - if (conn->timestamp) + if (_SO_GETOPT(conn->sconn.s_options, SO_TIMESTAMP)) { state.pr_msgbuf = cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMP, NULL, sizeof(struct timeval)); diff --git a/net/can/can_sendmsg.c b/net/can/can_sendmsg.c index 813be3586a817..5f13e99b88afc 100644 --- a/net/can/can_sendmsg.c +++ b/net/can/can_sendmsg.c @@ -202,7 +202,7 @@ ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg, } #if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) - if (conn->fd_frames) + if (_SO_GETOPT(conn->sconn.s_options, CAN_RAW_FD_FRAMES)) { if (msg->msg_iov->iov_len != CANFD_MTU && msg->msg_iov->iov_len != CAN_MTU) @@ -236,7 +236,7 @@ ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg, if (msg->msg_controllen > sizeof(struct cmsghdr)) { FAR struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); - if (conn->tx_deadline && + if (_SO_GETOPT(conn->sconn.s_options, CAN_RAW_TX_DEADLINE) && cmsg->cmsg_level == SOL_CAN_RAW && cmsg->cmsg_type == CAN_RAW_TX_DEADLINE && cmsg->cmsg_len == sizeof(struct timeval)) diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c index 5584f18c70086..66b4f8924c549 100644 --- a/net/can/can_setsockopt.c +++ b/net/can/can_setsockopt.c @@ -81,32 +81,6 @@ int can_setsockopt(FAR struct socket *psock, int level, int option, conn = psock->s_conn; -#ifdef CONFIG_NET_TIMESTAMP - - /* Generates a timestamp for each incoming packet */ - - if (level == SOL_SOCKET && option == SO_TIMESTAMP) - { - /* Verify that option is at least the size of an integer. */ - - if (value_len < sizeof(int32_t)) - { - return -EINVAL; - } - - /* Lock the network so that we have exclusive access to the socket - * options. - */ - - net_lock(); - - conn->timestamp = *((FAR int32_t *)value); - - net_unlock(); - return OK; - } -#endif - if (level != SOL_CAN_RAW) { return -ENOPROTOOPT; @@ -152,63 +126,53 @@ int can_setsockopt(FAR struct socket *psock, int level, int option, } break; - case CAN_RAW_ERR_FILTER: #ifdef CONFIG_NET_CAN_ERRORS + case CAN_RAW_ERR_FILTER: if (value_len != sizeof(can_err_mask_t)) { return -EINVAL; } conn->err_mask = *(FAR can_err_mask_t *)value & CAN_ERR_MASK; -#endif break; +#endif case CAN_RAW_LOOPBACK: - if (value_len != sizeof(conn->loopback)) - { - return -EINVAL; - } - - conn->loopback = *(FAR int32_t *)value; - - break; - case CAN_RAW_RECV_OWN_MSGS: - if (value_len != sizeof(conn->recv_own_msgs)) - { - return -EINVAL; - } - - conn->recv_own_msgs = *(FAR int32_t *)value; - - break; - #ifdef CONFIG_NET_CAN_CANFD case CAN_RAW_FD_FRAMES: - if (value_len != sizeof(conn->fd_frames)) +#endif +#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE + case CAN_RAW_TX_DEADLINE: +#endif + /* Verify that option is the size of an 'int'. Should also check + * that 'value' is properly aligned for an 'int' + */ + + if (value_len != sizeof(int)) { return -EINVAL; } - conn->fd_frames = *(FAR int32_t *)value; + /* Lock the network so that we have exclusive access to the socket + * options. + */ - break; -#endif + net_lock(); - case CAN_RAW_JOIN_FILTERS: - break; + /* Set or clear the option bit */ -#ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE - case CAN_RAW_TX_DEADLINE: - if (value_len != sizeof(conn->tx_deadline)) + if (*(FAR int *)value) { - return -EINVAL; + _SO_SETOPT(conn->sconn.s_options, option); + } + else + { + _SO_CLROPT(conn->sconn.s_options, option); } - conn->tx_deadline = *(FAR int32_t *)value; - + net_unlock(); break; -#endif #if CONFIG_NET_RECV_BUFSIZE > 0 case SO_RCVBUF: diff --git a/net/socket/getsockopt.c b/net/socket/getsockopt.c index d238023b4aa53..ee6d10bbfb716 100644 --- a/net/socket/getsockopt.c +++ b/net/socket/getsockopt.c @@ -154,6 +154,9 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option, * periodic transmission of probes */ case SO_OOBINLINE: /* Leaves received out-of-band data inline */ case SO_REUSEADDR: /* Allow reuse of local addresses */ +#ifdef CONFIG_NET_TIMESTAMP + case SO_TIMESTAMP: /* Generates a timestamp for each incoming packet */ +#endif { sockopt_t optionset; diff --git a/net/socket/setsockopt.c b/net/socket/setsockopt.c index 23356658ecbca..d4ec83c26bd30 100644 --- a/net/socket/setsockopt.c +++ b/net/socket/setsockopt.c @@ -137,6 +137,9 @@ static int psock_socketlevel_option(FAR struct socket *psock, int option, * periodic transmission of probes */ case SO_OOBINLINE: /* Leaves received out-of-band data inline */ case SO_REUSEADDR: /* Allow reuse of local addresses */ +#ifdef CONFIG_NET_TIMESTAMP + case SO_TIMESTAMP: /* Generates a timestamp for each incoming packet */ +#endif { int setting;