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:
zhanghongyu 2024-03-28 15:01:31 +08:00 committed by Xiang Xiao
parent 589bb56bcb
commit a9bff735e7
3 changed files with 133 additions and 37 deletions

View File

@ -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
* *

View File

@ -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 */

View File

@ -128,17 +128,18 @@ const uint8_t len_to_can_dlc[65] =
}; };
/**************************************************************************** /****************************************************************************
* Public Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: can_in * Name: can_input_conn
* *
* Description: * Description:
* Handle incoming packet input * Handle incoming packet input
* *
* Input Parameters: * Input Parameters:
* dev - The device driver structure containing the received packet * dev - The device driver structure containing the received packet
* conn - A pointer to the CAN connection structure
* *
* Returned Value: * Returned Value:
* OK The packet has been processed and can be deleted * OK The packet has been processed and can be deleted
@ -151,19 +152,12 @@ const uint8_t len_to_can_dlc[65] =
* *
****************************************************************************/ ****************************************************************************/
static int can_in(struct net_driver_s *dev) static int can_input_conn(FAR struct net_driver_s *dev,
{ FAR struct can_conn_s *conn)
FAR struct can_conn_s *conn = NULL;
int ret = OK;
uint16_t buflen = dev->d_len;
do
{
conn = can_nextconn(conn);
if (conn && (conn->dev == NULL || dev == conn->dev))
{ {
uint16_t flags; uint16_t flags;
uint16_t buflen = dev->d_len;
int ret = OK;
/* Setup for the application callback */ /* Setup for the application callback */
@ -190,13 +184,66 @@ static int can_in(struct net_driver_s *dev)
nwarn("WARNING: Packet not processed\n"); nwarn("WARNING: Packet not processed\n");
ret = -EAGAIN; ret = -EAGAIN;
} }
}
}
while (conn);
return ret; return ret;
} }
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: can_in
*
* Description:
* Handle incoming packet input
*
* Input Parameters:
* dev - The device driver structure containing the received packet
*
* 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_in(FAR struct net_driver_s *dev)
{
FAR struct can_conn_s *conn = can_active(dev, NULL);
FAR struct can_conn_s *nextconn;
/* Do we have second connection that can hold this packet? */
while ((nextconn = can_active(dev, conn)) != NULL)
{
/* Yes... There are multiple listeners on the same dev.
* We need to clone the packet and deliver it to each listener.
*/
FAR struct iob_s *iob = netdev_iob_clone(dev, false);
if (iob == NULL)
{
nerr("ERROR: IOB clone failed.\n");
break; /* We can still process one time without clone. */
}
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);
}
/**************************************************************************** /****************************************************************************
* Name: can_input * Name: can_input
* *