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 */
|
||||||
|
@ -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
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user