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 */ - - dev->d_appdata = dev->d_buf; - dev->d_sndlen = 0; - - /* Perform the application callback */ - - flags = can_callback(dev, conn, CAN_NEWDATA); - - /* If the operation was successful, the CAN_NEWDATA flag is removed - * and thus the packet can be deleted (OK will be returned). - */ - - if ((flags & CAN_NEWDATA) != 0) + if (conn && (conn->dev == 0x0 || dev == conn->dev)) { - /* 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. + uint16_t flags; + + /* Setup for the application callback */ + + dev->d_appdata = dev->d_buf; + dev->d_sndlen = 0; + dev->d_len = buflen; + + /* Perform the application callback */ + + flags = can_callback(dev, conn, CAN_NEWDATA); + + /* 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 */