net/can: deliver data into multiple CAN conn bound to same dev
Because CAN is a broadcast protocol, each conn needs to be given independent data to avoid mutual interference. Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
parent
589bb56bcb
commit
a9bff735e7
@ -184,6 +184,25 @@ void can_free(FAR struct can_conn_s *conn);
|
|||||||
|
|
||||||
FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
|
FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: can_active()
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Traverse the list of NetLink connections that match dev
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - The device to search for.
|
||||||
|
* conn - The current connection; may be NULL to start the search at the
|
||||||
|
* beginning
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* This function is called from NetLink device logic.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct can_conn_s *can_active(FAR struct net_driver_s *dev,
|
||||||
|
FAR struct can_conn_s *conn);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: can_callback
|
* Name: can_callback
|
||||||
*
|
*
|
||||||
|
@ -225,4 +225,34 @@ FAR struct can_conn_s *can_nextconn(FAR struct can_conn_s *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: can_active()
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Traverse the list of NetLink connections that match dev
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - The device to search for.
|
||||||
|
* conn - The current connection; may be NULL to start the search at the
|
||||||
|
* beginning
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* This function is called from NetLink device logic.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct can_conn_s *can_active(FAR struct net_driver_s *dev,
|
||||||
|
FAR struct can_conn_s *conn)
|
||||||
|
{
|
||||||
|
while ((conn = can_nextconn(conn)) != NULL)
|
||||||
|
{
|
||||||
|
if (conn->dev == NULL || conn->dev == dev)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET_CAN */
|
#endif /* CONFIG_NET_CAN */
|
||||||
|
@ -127,6 +127,67 @@ const uint8_t len_to_can_dlc[65] =
|
|||||||
15,
|
15,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: can_input_conn
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Handle incoming packet input
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - The device driver structure containing the received packet
|
||||||
|
* conn - A pointer to the CAN connection structure
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* OK The packet has been processed and can be deleted
|
||||||
|
* -EAGAIN There is a matching connection, but could not dispatch the packet
|
||||||
|
* yet. Useful when a packet arrives before a recv call is in
|
||||||
|
* place.
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* This function can be called from an interrupt.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int can_input_conn(FAR struct net_driver_s *dev,
|
||||||
|
FAR struct can_conn_s *conn)
|
||||||
|
{
|
||||||
|
uint16_t flags;
|
||||||
|
uint16_t buflen = dev->d_len;
|
||||||
|
int ret = OK;
|
||||||
|
|
||||||
|
/* 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).
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -151,50 +212,36 @@ const uint8_t len_to_can_dlc[65] =
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int can_in(struct net_driver_s *dev)
|
static int can_in(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
FAR struct can_conn_s *conn = NULL;
|
FAR struct can_conn_s *conn = can_active(dev, NULL);
|
||||||
int ret = OK;
|
FAR struct can_conn_s *nextconn;
|
||||||
uint16_t buflen = dev->d_len;
|
|
||||||
|
|
||||||
do
|
/* Do we have second connection that can hold this packet? */
|
||||||
|
|
||||||
|
while ((nextconn = can_active(dev, conn)) != NULL)
|
||||||
{
|
{
|
||||||
conn = can_nextconn(conn);
|
/* Yes... There are multiple listeners on the same dev.
|
||||||
|
* We need to clone the packet and deliver it to each listener.
|
||||||
|
*/
|
||||||
|
|
||||||
if (conn && (conn->dev == NULL || dev == conn->dev))
|
FAR struct iob_s *iob = netdev_iob_clone(dev, false);
|
||||||
|
|
||||||
|
if (iob == NULL)
|
||||||
{
|
{
|
||||||
uint16_t flags;
|
nerr("ERROR: IOB clone failed.\n");
|
||||||
|
break; /* We can still process one time without clone. */
|
||||||
/* 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).
|
|
||||||
*/
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
while (conn);
|
|
||||||
|
|
||||||
return ret;
|
can_input_conn(dev, conn);
|
||||||
|
|
||||||
|
netdev_iob_replace(dev, iob);
|
||||||
|
conn = nextconn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can deliver the packet directly to the last listener. */
|
||||||
|
|
||||||
|
return can_input_conn(dev, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
Loading…
x
Reference in New Issue
Block a user