You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/07/25 15:47:13 UTC
[incubator-nuttx] 02/09: SocketCAN: add non-blocking write
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 51a845ce54e38ca6ecc13c2fd7029802cb07076f
Author: Jari van Ewijk <ja...@nxp.com>
AuthorDate: Fri Jul 22 10:23:20 2022 +0200
SocketCAN: add non-blocking write
Co-authored-by: Peter van der Perk <pe...@nxp.com>
---
net/can/can.h | 26 ++++++++++++++++++++++++++
net/can/can_input.c | 52 ++++++++++++++++++++++++---------------------------
net/can/can_sendmsg.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
net/can/can_sockif.c | 10 +++-------
4 files changed, 99 insertions(+), 37 deletions(-)
diff --git a/net/can/can.h b/net/can/can.h
index 48f9e1087d..d317fea6f7 100644
--- a/net/can/can.h
+++ b/net/can/can.h
@@ -267,6 +267,32 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn);
+/****************************************************************************
+ * Name: psock_can_cansend
+ *
+ * Description:
+ * psock_can_cansend() returns a value indicating if a write to the socket
+ * would block. It is still possible that the write may block if another
+ * write occurs first.
+ *
+ * Input Parameters:
+ * psock An instance of the internal socket structure.
+ *
+ * Returned Value:
+ * OK
+ * At least one byte of data could be successfully written.
+ * -EWOULDBLOCK
+ * There is no room in the output buffer.
+ * -EBADF
+ * An invalid descriptor was specified.
+ *
+ * Assumptions:
+ * None
+ *
+ ****************************************************************************/
+
+int psock_can_cansend(FAR struct socket *psock);
+
/****************************************************************************
* Name: can_sendmsg
*
diff --git a/net/can/can_input.c b/net/can/can_input.c
index 024bb9aad5..7a073d566d 100644
--- a/net/can/can_input.c
+++ b/net/can/can_input.c
@@ -155,48 +155,44 @@ int can_input(struct net_driver_s *dev)
{
FAR struct can_conn_s *conn = NULL;
int ret = OK;
+ uint16_t buflen = dev->d_len;
do
{
- /* FIXME Support for multiple sockets??? */
-
conn = can_nextconn(conn);
- }
- while (conn && conn->dev != 0 && dev != conn->dev);
-
- if (conn)
- {
- uint16_t flags;
- /* Setup for the application callback */
+ if (conn && (conn->dev == 0x0 || dev == conn->dev))
+ {
+ uint16_t flags;
- dev->d_appdata = dev->d_buf;
- dev->d_sndlen = 0;
+ /* Setup for the application callback */
- /* Perform the application callback */
+ dev->d_appdata = dev->d_buf;
+ dev->d_sndlen = 0;
+ dev->d_len = buflen;
- flags = can_callback(dev, conn, CAN_NEWDATA);
+ /* Perform the application callback */
- /* If the operation was successful, the CAN_NEWDATA flag is removed
- * and thus the packet can be deleted (OK will be returned).
- */
+ flags = can_callback(dev, conn, CAN_NEWDATA);
- if ((flags & CAN_NEWDATA) != 0)
- {
- /* No.. the packet was not processed now. Return -EAGAIN so
- * that the driver may retry again later. We still need to
- * set d_len to zero so that the driver is aware that there
- * is nothing to be sent.
+ /* If the operation was successful, the CAN_NEWDATA flag is removed
+ * and thus the packet can be deleted (OK will be returned).
*/
- nwarn("WARNING: Packet not processed\n");
- ret = -EAGAIN;
+ if ((flags & CAN_NEWDATA) != 0)
+ {
+ /* No.. the packet was not processed now. Return -EAGAIN so
+ * that the driver may retry again later. We still need to
+ * set d_len to zero so that the driver is aware that there
+ * is nothing to be sent.
+ */
+
+ nwarn("WARNING: Packet not processed\n");
+ ret = -EAGAIN;
+ }
}
}
- else
- {
- ninfo("No CAN listener\n");
- }
+ while (conn);
return ret;
}
diff --git a/net/can/can_sendmsg.c b/net/can/can_sendmsg.c
index a7912d99d1..3ccea61826 100644
--- a/net/can/can_sendmsg.c
+++ b/net/can/can_sendmsg.c
@@ -259,10 +259,17 @@ ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
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.
+ * net_timedwait will also terminate if a signal is received.
*/
- ret = net_lockedwait(&state.snd_sem);
+ if (_SS_ISNONBLOCK(conn->sconn.s_flags) || (flags & MSG_DONTWAIT) != 0)
+ {
+ ret = net_timedwait(&state.snd_sem, 0);
+ }
+ else
+ {
+ ret = net_timedwait(&state.snd_sem, UINT_MAX);
+ }
/* Make sure that no further events are processed */
@@ -296,4 +303,41 @@ ssize_t can_sendmsg(FAR struct socket *psock, FAR struct msghdr *msg,
return state.snd_sent;
}
+/****************************************************************************
+ * Name: psock_can_cansend
+ *
+ * Description:
+ * psock_can_cansend() returns a value indicating if a write to the socket
+ * would block. No space in the buffer is actually reserved, so it is
+ * possible that the write may still block if the buffer is filled by
+ * another means.
+ *
+ * Input Parameters:
+ * psock An instance of the internal socket structure.
+ *
+ * Returned Value:
+ * OK
+ * At least one byte of data could be successfully written.
+ * -EWOULDBLOCK
+ * There is no room in the output buffer.
+ * -EBADF
+ * An invalid descriptor was specified.
+ *
+ ****************************************************************************/
+
+int psock_can_cansend(FAR struct socket *psock)
+{
+ /* Verify that we received a valid socket */
+
+ if (psock == NULL || psock->s_conn == NULL)
+ {
+ nerr("ERROR: Invalid socket\n");
+ return -EBADF;
+ }
+
+ /* TODO Query CAN driver mailboxes to see if there's mailbox available */
+
+ return OK;
+}
+
#endif /* CONFIG_NET && CONFIG_NET_CAN */
diff --git a/net/can/can_sockif.c b/net/can/can_sockif.c
index 780641f972..bddc3ef9b8 100644
--- a/net/can/can_sockif.c
+++ b/net/can/can_sockif.c
@@ -139,15 +139,13 @@ static uint16_t can_poll_eventhandler(FAR struct net_driver_s *dev,
eventset |= (POLLHUP | POLLERR);
}
-#if 0
/* A poll is a sign that we are free to send data. */
else if ((flags & CAN_POLL) != 0 &&
- psock_udp_cansend(info->psock) >= 0)
+ psock_can_cansend(info->psock) >= 0)
{
eventset |= (POLLOUT & info->fds->events);
}
-#endif
/* Awaken the caller of poll() is requested event occurred. */
@@ -608,14 +606,12 @@ static int can_poll_local(FAR struct socket *psock, FAR struct pollfd *fds,
fds->revents |= (POLLRDNORM & fds->events);
}
- #if 0
- if (psock_udp_cansend(psock) >= 0)
+ if (psock_can_cansend(psock) >= 0)
{
- /* Normal data may be sent without blocking (at least one byte). */
+ /* A CAN frame may be sent without blocking. */
fds->revents |= (POLLWRNORM & fds->events);
}
- #endif
/* Check if any requested events are already in effect */