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 4f7a02696e1b36d8c48e2b2c84aa82882dcebf70
Author: Peter van der Perk <peter.vanderp...@nxp.com>
AuthorDate: Fri Mar 13 18:12:29 2020 +0100

    Socket: Control message addded initial stubs for sendmsg()
---
 arch/arm/src/s32k1xx/Kconfig           |   1 +
 arch/arm/src/s32k1xx/s32k1xx_flexcan.c |   9 +-
 include/netpacket/can.h                |   2 +
 include/nuttx/net/net.h                |  13 ++-
 libs/libc/net/lib_recvmsg.c            |   4 +-
 libs/libc/net/lib_sendmsg.c            |   4 +-
 net/bluetooth/bluetooth_sockif.c       |   3 +-
 net/can/Kconfig                        |  20 ++++
 net/can/can.h                          |  16 +--
 net/can/can_getsockopt.c               |  21 ++++
 net/can/can_recvfrom.c                 | 191 +++++++++++++++------------------
 net/can/can_send.c                     |   4 +
 net/can/can_setsockopt.c               |  10 ++
 net/can/can_sockif.c                   |  51 ++++++++-
 net/icmp/icmp_sockif.c                 |   3 +-
 net/icmpv6/icmpv6_sockif.c             |   3 +-
 net/ieee802154/ieee802154_sockif.c     |   3 +-
 net/inet/inet_sockif.c                 |   3 +-
 net/local/local_sockif.c               |   3 +-
 net/netlink/netlink_sockif.c           |   3 +-
 net/pkt/pkt_sockif.c                   |   3 +-
 net/socket/Kconfig                     |  14 +--
 net/socket/Make.defs                   |   5 +-
 net/socket/recvmsg.c                   |   4 +-
 net/socket/{recvmsg.c => sendmsg.c}    |  68 ++++++------
 25 files changed, 282 insertions(+), 179 deletions(-)

diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig
index 68f9bb6..41638d0 100644
--- a/arch/arm/src/s32k1xx/Kconfig
+++ b/arch/arm/src/s32k1xx/Kconfig
@@ -152,6 +152,7 @@ config S32K1XX_ENET
 
 config S32K1XX_FLEXCAN
        bool "FLEXCAN"
+       select NET_CAN_HAVE_TX_DEADLINE
        default n
 
 menuconfig S32K1XX_LPI2C0
diff --git a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c 
b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
index 15e5b62..5c02aa0 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_flexcan.c
@@ -433,10 +433,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s 
*priv)
           mb->id.std = frame->can_id & MASKSTDID;
         }
 
-  #if 0
-      /* cs.rtr = frame.isRemoteTransmissionRequest(); */
-  #endif
-
+      cs.rtr = frame->can_id & FLAGRTR ? 1 : 0;
       cs.dlc = frame->can_dlc;
 
       mb->data[0].w00 = __builtin_bswap32(*(uint32_t *)&frame->data[0]);
@@ -458,9 +455,7 @@ static int s32k1xx_transmit(FAR struct s32k1xx_driver_s 
*priv)
           mb->id.std = frame->can_id & MASKSTDID;
         }
 
-#if 0
-      /* cs.rtr = frame.isRemoteTransmissionRequest(); */
-#endif
+      cs.rtr = frame->can_id & FLAGRTR ? 1 : 0;
 
       if (frame->len < 9)
         {
diff --git a/include/netpacket/can.h b/include/netpacket/can.h
index 4ea2104..bd0442d 100644
--- a/include/netpacket/can.h
+++ b/include/netpacket/can.h
@@ -75,6 +75,8 @@
                                  /* allow CAN FD frames (default:off) */
 #define CAN_RAW_JOIN_FILTERS   (__SO_PROTOCOL + 5)     
                                  /* all filters must match to trigger */
+#define CAN_RAW_TX_DEADLINE    (__SO_PROTOCOL + 6)
+                                 /* Abort frame when deadline has been passed 
*/
 
 /****************************************************************************
  * Public Types
diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h
index b7d759c..1c661b1 100644
--- a/include/nuttx/net/net.h
+++ b/include/nuttx/net/net.h
@@ -214,7 +214,7 @@ struct sock_intf_s
                     FAR socklen_t *fromlen);
 #ifdef CONFIG_NET_RECVMSG_CMSG
   CODE ssize_t    (*si_recvmsg)(FAR struct socket *psock,
-                FAR struct msghdr *msg, int flags);
+                           FAR struct msghdr *msg, int flags);
 #endif
   CODE int        (*si_close)(FAR struct socket *psock);
 #ifdef CONFIG_NET_USRSOCK
@@ -504,9 +504,9 @@ FAR struct iob_s *net_ioballoc(bool throttled, enum 
iob_user_e consumerid);
  * Description:
  *   Check if the socket descriptor is valid for the provided TCB and if it
  *   supports the requested access.  This trivial operation is part of the
- *   fdopen() operation when the fdopen() is performed on a socket
- *   descriptor.  It simply performs some sanity checking before permitting
- *   the socket descriptor to be wrapped as a C FILE stream.
+ *   fdopen() operation when the fdopen() is performed on a socket descriptor.
+ *   It simply performs some sanity checking before permitting the socket
+ *   descriptor to be wrapped as a C FILE stream.
  *
  ****************************************************************************/
 
@@ -739,8 +739,7 @@ int psock_listen(FAR struct socket *psock, int backlog);
  * Input Parameters:
  *   psock    Reference to the listening socket structure
  *   addr     Receives the address of the connecting client
- *   addrlen  Input: allocated size of 'addr',
- *            Return: returned size of 'addr'
+ *   addrlen  Input: allocated size of 'addr', Return: returned size of 'addr'
  *   newsock  Location to return the accepted socket information.
  *
  * Returned Value:
@@ -1564,7 +1563,7 @@ int net_vfcntl(int sockfd, int cmd, va_list ap);
  *
  * Input Parameters:
  *   dev    - The device driver structure to be registered.
- *   lltype - Link level protocol used by driver (Ethernet, SLIP, TUN, ...
+ *   lltype - Link level protocol used by the driver (Ethernet, SLIP, TUN, ...
  *
  * Returned Value:
  *   0:Success; negated errno on failure
diff --git a/libs/libc/net/lib_recvmsg.c b/libs/libc/net/lib_recvmsg.c
index 5200acd..071c189 100644
--- a/libs/libc/net/lib_recvmsg.c
+++ b/libs/libc/net/lib_recvmsg.c
@@ -39,7 +39,7 @@
 
 #include <nuttx/config.h>
 
-#if defined(CONFIG_NET) && !defined(CONFIG_NET_RECVMSG_CMSG)
+#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -87,4 +87,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
     }
 }
 
-#endif /* CONFIG_NET && !CONFIG_NET_RECVMSG_CMSG */
+#endif /* CONFIG_NET && !CONFIG_NET_CMSG */
diff --git a/libs/libc/net/lib_sendmsg.c b/libs/libc/net/lib_sendmsg.c
index 0d09faa..9f98e51 100644
--- a/libs/libc/net/lib_sendmsg.c
+++ b/libs/libc/net/lib_sendmsg.c
@@ -39,7 +39,7 @@
 
 #include <nuttx/config.h>
 
-#ifdef CONFIG_NET
+#if defined(CONFIG_NET) && !defined(CONFIG_NET_CMSG)
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -86,4 +86,4 @@ ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
     }
 }
 
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET && !CONFIG_NET_CMSG */
diff --git a/net/bluetooth/bluetooth_sockif.c b/net/bluetooth/bluetooth_sockif.c
index fd6d95f..4057d93 100644
--- a/net/bluetooth/bluetooth_sockif.c
+++ b/net/bluetooth/bluetooth_sockif.c
@@ -109,8 +109,9 @@ const struct sock_intf_s g_bluetooth_sockif =
   NULL,                  /* si_sendfile */
 #endif
   bluetooth_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,                  /* si_recvmsg */
+  NULL,                  /* si_sendmsg */
 #endif
   bluetooth_close        /* si_close */
 };
diff --git a/net/can/Kconfig b/net/can/Kconfig
index 3b2e450..ac94021 100644
--- a/net/can/Kconfig
+++ b/net/can/Kconfig
@@ -18,6 +18,10 @@ config NET_CAN
 
 if NET_CAN
 
+config NET_CAN_HAVE_TX_DEADLINE
+       bool
+       default n
+
 config CAN_CONNS
        int "Number of CAN connections"
        default 4
@@ -27,9 +31,25 @@ config CAN_CONNS
 config NET_CAN_SOCK_OPTS
        bool "sockopt support"
        default n
+       select NET_SOCKOPTS
        select NET_CANPROTO_OPTIONS
        ---help---
                Enable support for the CAN socket options
+                               
+config NET_CAN_RAW_TX_DEADLINE
+       bool "TX deadline sockopt"
+       default n
+       depends on NET_CAN_SOCK_OPTS && NET_CAN_HAVE_TX_DEADLINE
+       select NET_CMSG
+       ---help---
+           Note: Non-standard SocketCAN sockopt, but this options helps us in
+           real-time use cases.
+           
+               When the CAN_RAW_TX_DEADLINE sockopt is enabled. The user can 
send 
+               CAN frames using sendmsg() function and add a deadline timespec 
+               value in the CMSG data. When the deadline has been passed and 
the
+               CAN frame is still in the HW TX mailbox then the CAN driver 
will 
+               discard the CAN frame automatically.
                
 config NET_CAN_RAW_FILTER_MAX
        int "CAN_RAW_FILTER max filter count"
diff --git a/net/can/can.h b/net/can/can.h
index 7c6b614..00c297d 100644
--- a/net/can/can.h
+++ b/net/can/can.h
@@ -104,20 +104,23 @@ 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;
   struct can_filter filters[CONFIG_NET_CAN_RAW_FILTER_MAX];
   int32_t filter_count;
-
-  /* TODO add filter support */
+# ifdef CONFIG_NET_CAN_RAW_TX_DEADLINE
+  int32_t tx_deadline;
+# endif
 #endif
-
+  
 #ifdef CONFIG_NET_TIMESTAMP
   FAR struct socket *psock; /* Needed to get SO_TIMESTAMP value */
 #endif
+
+  
 };
 
 /****************************************************************************
@@ -166,8 +169,8 @@ FAR struct can_conn_s *can_alloc(void);
  * Name: can_free()
  *
  * Description:
- *   Free a NetLink connection structure that is no longer in use. This
- *   should be done by the implementation of close().
+ *   Free a NetLink connection structure that is no longer in use. This should
+ *   be done by the implementation of close().
  *
  ****************************************************************************/
 
@@ -256,6 +259,7 @@ uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR 
uint8_t *buffer,
  *
  ****************************************************************************/
 
+
 ssize_t can_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
                      int flags, FAR struct sockaddr *from,
                      FAR socklen_t *fromlen);
diff --git a/net/can/can_getsockopt.c b/net/can/can_getsockopt.c
index 238695c..17184e2 100644
--- a/net/can/can_getsockopt.c
+++ b/net/can/can_getsockopt.c
@@ -188,6 +188,27 @@ int can_getsockopt(FAR struct socket *psock, int option,
       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.
+             */
+
+            ret              = -EINVAL;
+          }
+        else
+          {
+            FAR int *tx_deadline = (FAR int32_t *)value;
+            *tx_deadline         = conn->tx_deadline;
+            *value_len         = sizeof(conn->tx_deadline);
+            ret                = OK;
+          }
+        break;
+#endif
+
       default:
         nerr("ERROR: Unrecognized RAW CAN socket option: %d\n", option);
         ret = -ENOPROTOOPT;
diff --git a/net/can/can_recvfrom.c b/net/can/can_recvfrom.c
index 2211ed0..d9ed8cb 100644
--- a/net/can/can_recvfrom.c
+++ b/net/can/can_recvfrom.c
@@ -50,19 +50,20 @@
 #include <sys/time.h>
 #endif
 
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
 
 struct can_recvfrom_s
 {
-  FAR struct socket *pr_sock;          /* The parent socket structure */
+  FAR struct socket       *pr_sock;      /* The parent socket structure */
   FAR struct devif_callback_s *pr_cb;  /* Reference to callback instance */
   sem_t        pr_sem;                 /* Semaphore signals recv completion */
   size_t       pr_buflen;              /* Length of receive buffer */
   FAR uint8_t *pr_buffer;              /* Pointer to receive buffer */
   ssize_t      pr_recvlen;             /* The received length */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   size_t       pr_msglen;              /* Length of msg buffer */
   FAR uint8_t *pr_msgbuf;              /* Pointer to msg buffer */
 #endif
@@ -232,15 +233,14 @@ static inline void can_newdata(FAR struct net_driver_s 
*dev,
 
 static inline int can_readahead(struct can_recvfrom_s *pstate)
 {
-  FAR struct can_conn_s *conn =
-    (FAR struct can_conn_s *) pstate->pr_sock->s_conn;
+  FAR struct can_conn_s *conn = (FAR struct can_conn_s 
*)pstate->pr_sock->s_conn;
   FAR struct iob_s *iob;
   int recvlen;
 
   /* Check there is any CAN data already buffered in a read-ahead
    * buffer.
    */
-
+  
   pstate->pr_recvlen = -1;
 
   if ((iob = iob_peek_queue(&conn->readahead)) != NULL &&
@@ -287,16 +287,15 @@ 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;
-            }
-        }
+         /* 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;
     }
@@ -320,14 +319,13 @@ static inline int can_readahead(struct can_recvfrom_s 
*pstate)
  *   The network is locked.
  *
  ****************************************************************************/
-
 #ifdef CONFIG_NET_TIMESTAMP
-static inline int can_readahead_timestamp(struct can_conn_s *conn,
-                                          FAR uint8_t *buffer)
+static inline int can_readahead_timestamp(struct can_conn_s *conn, FAR uint8_t 
*buffer)
 {
   FAR struct iob_s *iob;
   int recvlen;
 
+
   if ((iob = iob_peek_queue(&conn->readahead)) != NULL)
     {
       DEBUGASSERT(iob->io_pktlen > 0);
@@ -381,27 +379,26 @@ static inline int can_readahead_timestamp(struct 
can_conn_s *conn,
 #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++)
+  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;
-            }
-        }
+         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
@@ -419,50 +416,46 @@ static uint16_t can_recvfrom_eventhandler(FAR struct 
net_driver_s *dev,
     {
       if ((flags & CAN_NEWDATA) != 0)
         {
-          /* If a new packet is available, check receive filters
-           * when is valid then complete the read action.
-           */
+         /* 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;
-            }
+         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;
-              if (cfd->len > CAN_MAX_DLEN)
-                {
-                  /* DO WE NEED TO CLEAR FLAGS?? */
-
-                  flags &= ~CAN_NEWDATA;
-                  return flags;
-                }
-            }
+         /* 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);
 
 #ifdef CONFIG_NET_TIMESTAMP
-          if (pstate->pr_sock->s_timestamp)
-            {
-              if (pstate->pr_msglen == sizeof(struct timeval))
-                {
-                  can_readahead_timestamp(conn, pstate->pr_msgbuf);
-                }
-              else
-                {
-                  /* We still have to consume the data otherwise IOB gets full 
*/
-
-                  uint8_t dummy_buf[sizeof(struct timeval)];
-                  can_readahead_timestamp(conn, &dummy_buf);
-                }
-            }
+                 if(pstate->pr_sock->s_timestamp)
+                       {
+                         if(pstate->pr_msglen == sizeof(struct timeval))
+                           {
+                                 can_readahead_timestamp(conn, 
pstate->pr_msgbuf);
+                           }
+                         else
+                           {
+                               /* We still have to consume the data otherwise 
IOB gets full */
+                                 uint8_t dummy_buf[sizeof(struct timeval)];
+                                 can_readahead_timestamp(conn, &dummy_buf);
+                           }
+                       }
 #endif
 
           /* We are finished. */
@@ -515,7 +508,6 @@ static ssize_t can_recvfrom_result(int result,
   if (pstate->pr_result < 0)
     {
       /* This might return EAGAIN on a timeout */
-
       return pstate->pr_result;
     }
 
@@ -600,10 +592,10 @@ ssize_t can_recvfrom(FAR struct socket *psock, FAR void 
*buf,
 
   ret = can_readahead(&state);
   if (ret > 0)
-    {
+    {      
       goto errout_with_state;
     }
-
+    
   ret = state.pr_recvlen;
 
   /* Handle non-blocking CAN sockets */
@@ -618,7 +610,7 @@ ssize_t can_recvfrom(FAR struct socket *psock, FAR void 
*buf,
         {
           /* Nothing was received */
 
-          ret = -EAGAIN;
+          ret = -EAGAIN;          
           goto errout_with_state;
         }
     }
@@ -683,7 +675,6 @@ errout_with_state:
  *   flags    Receive flags (ignored)
  *
  ****************************************************************************/
-
 #ifdef CONFIG_NET_RECVMSG_CMSG
 ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
                     size_t len, int flags)
@@ -716,22 +707,20 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
   nxsem_init(&state.pr_sem, 0, 0); /* Doesn't really fail */
   nxsem_setprotocol(&state.pr_sem, SEM_PRIO_NONE);
 
+
   state.pr_buflen = msg->msg_iov->iov_len;
   state.pr_buffer = msg->msg_iov->iov_base;
-
 #ifdef CONFIG_NET_TIMESTAMP
-  if (psock->s_timestamp && msg->msg_controllen ==
-        (sizeof(struct cmsghdr) + sizeof(struct timeval)))
+  if(psock->s_timestamp && msg->msg_controllen == (sizeof(struct cmsghdr) + 
sizeof(struct timeval)))
     {
-      struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
-      state.pr_msglen = sizeof(struct timeval);
-      state.pr_msgbuf = CMSG_DATA(cmsg);
-      cmsg->cmsg_level = SOL_SOCKET;
-      cmsg->cmsg_type = SO_TIMESTAMP;
-      cmsg->cmsg_len = state.pr_msglen;
+         struct cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
+         state.pr_msglen = sizeof(struct timeval);
+         state.pr_msgbuf = CMSG_DATA(cmsg);
+         cmsg->cmsg_level = SOL_SOCKET;
+         cmsg->cmsg_type = SO_TIMESTAMP;
+         cmsg->cmsg_len = state.pr_msglen;
     }
 #endif
-
   state.pr_sock   = psock;
 
   /* Handle any any CAN data already buffered in a read-ahead buffer.  NOTE
@@ -743,22 +732,20 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct 
msghdr *msg,
   if (ret > 0)
     {
 #ifdef CONFIG_NET_TIMESTAMP
-      if (psock->s_timestamp)
-        {
-          if (state.pr_msglen == sizeof(struct timeval))
-            {
-              can_readahead_timestamp(conn, state.pr_msgbuf);
-            }
-          else
-            {
-              /* We still have to consume the data otherwise IOB gets full */
-
-              uint8_t dummy_buf[sizeof(struct timeval)];
-              can_readahead_timestamp(conn, &dummy_buf);
-            }
-        }
+         if(psock->s_timestamp)
+           {
+                 if(state.pr_msglen == sizeof(struct timeval))
+                   {
+                         can_readahead_timestamp(conn, state.pr_msgbuf);
+                   }
+                 else
+                   {
+                       /* We still have to consume the data otherwise IOB gets 
full */
+                   uint8_t dummy_buf[sizeof(struct timeval)];
+                       can_readahead_timestamp(conn, &dummy_buf);
+                   }
+           }
 #endif
-
       goto errout_with_state;
     }
 
diff --git a/net/can/can_send.c b/net/can/can_send.c
index 644adc3..dfb03d0 100644
--- a/net/can/can_send.c
+++ b/net/can/can_send.c
@@ -76,6 +76,10 @@ struct send_s
   sem_t                   snd_sem;     /* Used to wake up the waiting thread */
   FAR const uint8_t      *snd_buffer;  /* Points to the buffer of data to send 
*/
   size_t                  snd_buflen;  /* Number of bytes in the buffer to 
send */
+#ifdef CONFIG_NET_CMSG
+  size_t                  pr_msglen;   /* Length of msg buffer */
+  FAR uint8_t            *pr_msgbuf;   /* Pointer to msg buffer */
+#endif
   ssize_t                 snd_sent;    /* The number of bytes sent */
 };
 
diff --git a/net/can/can_setsockopt.c b/net/can/can_setsockopt.c
index 6858c1a..ac9f912 100644
--- a/net/can/can_setsockopt.c
+++ b/net/can/can_setsockopt.c
@@ -147,6 +147,16 @@ int can_setsockopt(FAR struct socket *psock, int option,
       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))
+                       return -EINVAL;
+
+               conn->tx_deadline = *(FAR int32_t *)value;
+
+               break;
+#endif
+
       default:
         nerr("ERROR: Unrecognized CAN option: %d\n", option);
         ret = -ENOPROTOOPT;
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
index 737788e..09a61d0 100644
--- a/net/can/can_sockif.c
+++ b/net/can/can_sockif.c
@@ -69,6 +69,10 @@ static ssize_t can_send(FAR struct socket *psock,
 static ssize_t can_sendto(FAR struct socket *psock, FAR const void *buf,
               size_t len, int flags, FAR const struct sockaddr *to,
               socklen_t tolen);
+#ifdef CONFIG_NET_CMSG
+static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                    size_t len, int flags);
+#endif
 static int can_close(FAR struct socket *psock);
 
 /****************************************************************************
@@ -93,8 +97,9 @@ const struct sock_intf_s g_can_sockif =
   NULL,             /* si_sendfile */
 #endif
   can_recvfrom,     /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   can_recvmsg,      /* si_recvmsg */
+  can_sendmsg,      /* si_sendmsg */
 #endif
   can_close         /* si_close */
 };
@@ -774,6 +779,50 @@ static ssize_t can_sendto(FAR struct socket *psock, FAR 
const void *buf,
 }
 
 /****************************************************************************
+ * Name: can_sendmsg
+ *
+ * Description:
+ *   The can_sendmsg() send a CAN frame to psock
+ *
+ * Input Parameters:
+ *   psock - An instance of the internal socket structure.
+ *   msg   - CAN frame and optional CMSG
+ *   flags - Send flags (ignored)
+ *
+ * Returned Value:
+ *   On success, returns the number of characters sent.  On  error, a negated
+ *   errno value is returned (see send() for the list of appropriate error
+ *   values.
+ *
+ ****************************************************************************/
+#ifdef CONFIG_NET_CMSG
+static ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+                    size_t len, int flags);
+{
+  ssize_t ret;
+
+  /* Only SOCK_RAW is supported */
+
+  if (psock->s_type == SOCK_RAW)
+    {
+      /* Raw packet send */
+
+      ret = psock_can_send(psock, buf, len);
+    }
+  else
+    {
+      /* EDESTADDRREQ.  Signifies that the socket is not connection-mode and
+       * no peer address is set.
+       */
+
+      ret = -EDESTADDRREQ;
+    }
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
  * Name: can_close
  *
  * Description:
diff --git a/net/icmp/icmp_sockif.c b/net/icmp/icmp_sockif.c
index c81592e..ebe2bab 100644
--- a/net/icmp/icmp_sockif.c
+++ b/net/icmp/icmp_sockif.c
@@ -102,8 +102,9 @@ const struct sock_intf_s g_icmp_sockif =
   NULL,             /* si_sendfile */
 #endif
   icmp_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,             /* si_recvmsg */
+  NULL,             /* si_sendmsg */
 #endif
   icmp_close        /* si_close */
 };
diff --git a/net/icmpv6/icmpv6_sockif.c b/net/icmpv6/icmpv6_sockif.c
index 29e5e47..5adae60 100644
--- a/net/icmpv6/icmpv6_sockif.c
+++ b/net/icmpv6/icmpv6_sockif.c
@@ -102,8 +102,9 @@ const struct sock_intf_s g_icmpv6_sockif =
   NULL,               /* si_sendfile */
 #endif
   icmpv6_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,               /* si_recvmsg */
+  NULL,               /* si_sendmsg */
 #endif
   icmpv6_close        /* si_close */
 };
diff --git a/net/ieee802154/ieee802154_sockif.c 
b/net/ieee802154/ieee802154_sockif.c
index d1ac29b..6c0f88a 100644
--- a/net/ieee802154/ieee802154_sockif.c
+++ b/net/ieee802154/ieee802154_sockif.c
@@ -107,8 +107,9 @@ const struct sock_intf_s g_ieee802154_sockif =
   NULL,                   /* si_sendfile */
 #endif
   ieee802154_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,                   /* si_recvmsg */
+  NULL,                   /* si_sendmsg */
 #endif
   ieee802154_close        /* si_close */
 };
diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c
index 0980989..abdef2e 100644
--- a/net/inet/inet_sockif.c
+++ b/net/inet/inet_sockif.c
@@ -117,8 +117,9 @@ static const struct sock_intf_s g_inet_sockif =
   inet_sendfile,    /* si_sendfile */
 #endif
   inet_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,             /* si_recvmsg */
+  NULL,             /* si_sendmsg */
 #endif
   inet_close        /* si_close */
 };
diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c
index 62d56b5..cd9bd66 100644
--- a/net/local/local_sockif.c
+++ b/net/local/local_sockif.c
@@ -110,8 +110,9 @@ const struct sock_intf_s g_local_sockif =
   NULL,              /* si_sendfile */
 #endif
   local_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,              /* si_recvmsg */
+  NULL,              /* si_sendmsg */
 #endif
   local_close        /* si_close */
 };
diff --git a/net/netlink/netlink_sockif.c b/net/netlink/netlink_sockif.c
index 1c0c815..b3ef9ad 100644
--- a/net/netlink/netlink_sockif.c
+++ b/net/netlink/netlink_sockif.c
@@ -111,8 +111,9 @@ const struct sock_intf_s g_netlink_sockif =
   NULL,                 /* si_sendfile */
 #endif
   netlink_recvfrom,     /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,                 /* si_recvmsg */
+  NULL,                 /* si_sendmsg */
 #endif
   netlink_close         /* si_close */
 };
diff --git a/net/pkt/pkt_sockif.c b/net/pkt/pkt_sockif.c
index bbabf42..dbf3e3c 100644
--- a/net/pkt/pkt_sockif.c
+++ b/net/pkt/pkt_sockif.c
@@ -108,8 +108,9 @@ const struct sock_intf_s g_pkt_sockif =
   NULL,            /* si_sendfile */
 #endif
   pkt_recvfrom,    /* si_recvfrom */
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
   NULL,            /* si_recvmsg */
+  NULL,            /* si_sendmsg */
 #endif
   pkt_close        /* si_close */
 };
diff --git a/net/socket/Kconfig b/net/socket/Kconfig
index f4c9408..f13e22d 100644
--- a/net/socket/Kconfig
+++ b/net/socket/Kconfig
@@ -58,18 +58,20 @@ config NET_SOLINGER
 config NET_TIMESTAMP
        bool "SO_TIMESTAMP socket option"
        default n
-       depends on NET_CAN && NET_RECVMSG_CMSG
+       depends on NET_CAN
+       select NET_CMSG
        ---help---
                Enable or disable support for the SO_TIMESTAMP socket option. 
Currently only tested & implemented in SocketCAN but should work on all sockets
 
 endif # NET_SOCKOPTS
 
-config NET_RECVMSG_CMSG
-       bool "recvmsg() control messages (CMSG) support"
+config NET_CMSG
+       bool "Control messages (CMSG) support"
        default n
        ---help---
-               Enable or disable support for control messages in the recvmsg 
function.
-               Control messages (also defined in POSIX 1003.1g as ancillary 
data object information).
-               Includes additional information on the packet received.
+               Enable or disable support for control messages in the recvmsg() 
and
+               sendmsg() function. Control messages (also defined in POSIX 
1003.1g 
+               as ancillary data object information). Includes additional 
+               information on the packet received or to be transmitted.
 
 endmenu # Socket Support
diff --git a/net/socket/Make.defs b/net/socket/Make.defs
index 2be9dbf..6bf79ed 100644
--- a/net/socket/Make.defs
+++ b/net/socket/Make.defs
@@ -75,7 +75,8 @@ endif
 DEPPATH += --dep-path socket
 VPATH += :socket
 
-# Support for recvmsg() with control messages (CMSG)
-ifeq ($(CONFIG_NET_RECVMSG_CMSG),y)
+# Support for control messages (CMSG)
+ifeq ($(CONFIG_NET_CMSG),y)
 SOCK_CSRCS += recvmsg.c
+SOCK_CSRCS += sendmsg.c
 endif
diff --git a/net/socket/recvmsg.c b/net/socket/recvmsg.c
index 17d4dfe..800eeb1 100644
--- a/net/socket/recvmsg.c
+++ b/net/socket/recvmsg.c
@@ -47,7 +47,7 @@
 
 #include "socket/socket.h"
 
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
 
 /****************************************************************************
  * Public Functions
@@ -235,4 +235,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int 
flags)
   return ret;
 }
 
-#endif /* CONFIG_NET_RECVMSG_CMSG */
+#endif /* CONFIG_NET_CMSG */
diff --git a/net/socket/recvmsg.c b/net/socket/sendmsg.c
similarity index 78%
copy from net/socket/recvmsg.c
copy to net/socket/sendmsg.c
index 17d4dfe..3bc32e8 100644
--- a/net/socket/recvmsg.c
+++ b/net/socket/sendmsg.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * net/socket/recvmsg.c
+ * net/socket/sendmsg.c
  *
  *   Copyright (C) 2007-2009, 2011-2017, 2019 Gregory Nutt. All rights 
reserved.
  *   Author: Gregory Nutt <gn...@nuttx.org>
@@ -47,20 +47,20 @@
 
 #include "socket/socket.h"
 
-#ifdef CONFIG_NET_RECVMSG_CMSG
+#ifdef CONFIG_NET_CMSG
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: psock_recvmsg
+ * Name: psock_sendmsg
  *
  * Description:
- *   psock_recvfrom() receives messages from a socket, and may be used to
- *   receive data on a socket whether or not it is connection-oriented.
+ *   psock_sendfrom() sends messages to a socket, and may be used to
+ *   send data on a socket whether or not it is connection-oriented.
  *   This is an internal OS interface.  It is functionally equivalent to
- *   recvfrom() except that:
+ *   sendfrom() except that:
  *
  *   - It is not a cancellation point,
  *   - It does not modify the errno variable, and
@@ -69,20 +69,20 @@
  *
  * Input Parameters:
  *   psock   - A pointer to a NuttX-specific, internal socket structure
- *   msg      Buffer to receive msg
+ *   msg     - Buffer to of the msg
  *   len     - Length of buffer
  *   flags   - Receive flags
  *
  * Returned Value:
  *   On success, returns the number of characters sent.  If no data is
  *   available to be received and the peer has performed an orderly shutdown,
- *   recv() will return 0.  Otherwise, on any failure, a negated errno value
+ *   send() will return 0.  Otherwise, on any failure, a negated errno value
  *   is returned (see comments with send() for a list of appropriate errno
  *   values).
  *
  ****************************************************************************/
 
-ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
+ssize_t psock_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
                        int flags)
 {
   /* Verify that non-NULL pointers were passed */
@@ -103,38 +103,38 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR 
struct msghdr *msg,
       return -EBADF;
     }
 
-  /* Let logic specific to this address family handle the recvfrom()
+  /* Let logic specific to this address family handle the sendfrom()
    * operation.
    */
 
   DEBUGASSERT(psock->s_sockif != NULL &&
-              (psock->s_sockif->si_recvmsg != NULL ||
-               psock->s_sockif->si_recvfrom != NULL));
+              (psock->s_sockif->si_sendmsg != NULL ||
+               psock->s_sockif->si_sendto != NULL));
 
-  if(psock->s_sockif->si_recvmsg != NULL)
+  if(psock->s_sockif->si_sendmsg != NULL)
     {
-         return psock->s_sockif->si_recvmsg(psock, msg, flags);
+         return psock->s_sockif->si_sendmsg(psock, msg, flags);
     }
   else
     {
-         /* Socket doesn't implement si_recvmsg fallback to si_recvfrom */
-         FAR void *buf             = msg->msg_iov->iov_base;
-         FAR struct sockaddr *from = msg->msg_name;
-         FAR socklen_t *fromlen    = (FAR socklen_t *)&msg->msg_namelen;
-         size_t len                = msg->msg_iov->iov_len;
-         return psock->s_sockif->si_recvfrom(psock, buf, len, flags, from, 
fromlen);
+         /* Socket doesn't implement si_sendmsg fallback to si_sendto */
+         FAR void *buf           = msg->msg_iov->iov_base;
+         FAR struct sockaddr *to = msg->msg_name;
+         socklen_t tolen         = msg->msg_namelen;
+         size_t len              = msg->msg_iov->iov_len;
+         return psock->s_sockif->si_sendto(psock, buf, len, flags, to, tolen);
     }
 
 }
 
 /****************************************************************************
- * Name: nx_recvfrom
+ * Name: nx_sendfrom
  *
  * Description:
- *   nx_recvfrom() receives messages from a socket, and may be used to
+ *   nx_sendfrom() receives messages from a socket, and may be used to
  *   receive data on a socket whether or not it is connection-oriented.
  *   This is an internal OS interface.  It is functionally equivalent to
- *   recvfrom() except that:
+ *   sendfrom() except that:
  *
  *   - It is not a cancellation point, and
  *   - It does not modify the errno variable.
@@ -148,13 +148,13 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR 
struct msghdr *msg,
  * Returned Value:
  *   On success, returns the number of characters sent.  If no data is
  *   available to be received and the peer has performed an orderly shutdown,
- *   recv() will return 0.  Otherwise, on any failure, a negated errno value
+ *   send() will return 0.  Otherwise, on any failure, a negated errno value
  *   is returned (see comments with send() for a list of appropriate errno
  *   values).
  *
  ****************************************************************************/
 
-ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+ssize_t nx_sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
 {
   FAR struct socket *psock;
 
@@ -162,16 +162,16 @@ ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, 
int flags)
 
   psock = sockfd_socket(sockfd);
 
-  /* Then let psock_recvmsg() do all of the work */
+  /* Then let psock_sendmsg() do all of the work */
 
-  return psock_recvmsg(psock, msg, flags);
+  return psock_sendmsg(psock, msg, flags);
 }
 
 /****************************************************************************
- * Function: recvmsg
+ * Function: sendmsg
  *
  * Description:
- *   The recvmsg() call is identical to recvfrom() with a NULL from parameter.
+ *   The sendmsg() call is identical to sendfrom() with a NULL from parameter.
  *
  * Parameters:
  *   sockfd   Socket descriptor of socket
@@ -209,12 +209,12 @@ ssize_t nx_recvmsg(int sockfd, FAR struct msghdr *msg, 
int flags)
  *
  ****************************************************************************/
 
-ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int flags)
+ssize_t sendmsg(int sockfd, FAR struct msghdr *msg, int flags)
 {
   FAR struct socket *psock;
   ssize_t ret;
 
-  /* recvfrom() is a cancellation point */
+  /* sendfrom() is a cancellation point */
 
   enter_cancellation_point();
 
@@ -222,9 +222,9 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int 
flags)
 
   psock = sockfd_socket(sockfd);
 
-  /* Let psock_recvfrom() do all of the work */
+  /* Let psock_sendfrom() do all of the work */
 
-  ret = psock_recvmsg(psock, msg, flags);
+  ret = psock_sendmsg(psock, msg, flags);
   if (ret < 0)
     {
       _SO_SETERRNO(psock, -ret);
@@ -235,4 +235,4 @@ ssize_t recvmsg(int sockfd, FAR struct msghdr *msg, int 
flags)
   return ret;
 }
 
-#endif /* CONFIG_NET_RECVMSG_CMSG */
+#endif /* CONFIG_NET_CMSG */

Reply via email to