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/nuttx.git
commit 34b350e66ef4b40a9e3e6eda10cdee748ed51c3e Author: zhanghongyu <[email protected]> AuthorDate: Wed Mar 26 21:34:49 2025 +0800 drivers/net/rpmsgdrv.c: add bidirectional data netdev support, clien side It's the first simple version of rpmsg-net, include: - Transfer command with data copy (maybe optimize later), no need to ack - Control command with ack, but only ifup/ifdown no need to ack - Client side: Another module can call `net_rpmsg_drv_alloc` to create netdev and register it. Signed-off-by: Zhe Weng <[email protected]> --- drivers/net/rpmsgdrv.c | 264 ++++++++++++++++++++++++++++++++++--------- include/nuttx/net/rpmsg.h | 2 +- include/nuttx/net/rpmsgdrv.h | 88 ++++++++++++++- 3 files changed, 296 insertions(+), 58 deletions(-) diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index e9ffc5d4637..da8cac0210c 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -71,9 +71,14 @@ struct net_rpmsg_drv_cookie_s struct net_rpmsg_drv_s { - FAR const char *cpuname; - FAR const char *devname; + char cpuname[RPMSG_NAME_SIZE]; netpkt_queue_t rxqueue; /* RX packet queue */ + FAR void *priv; /* Private data for upper layer */ + net_rpmsg_drv_cb_t cb; /* IFUP/DOWN Callback function */ + sem_t wait; /* Wait sem, used for preventing any + * operation until the connection + * between two cpu established. + */ struct rpmsg_endpoint ept; /* This holds the information visible to the NuttX network */ @@ -92,6 +97,12 @@ struct net_rpmsg_drv_s static int net_rpmsg_drv_default_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); +static int net_rpmsg_drv_ifup_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); +static int net_rpmsg_drv_ifdown_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv); static int net_rpmsg_drv_sockioctl_handler(FAR struct rpmsg_endpoint *ept, FAR void *data, size_t len, uint32_t src, FAR void *priv); @@ -147,8 +158,8 @@ static int net_rpmsg_drv_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, static const rpmsg_ept_cb g_net_rpmsg_drv_handler[] = { - [NET_RPMSG_IFUP] = net_rpmsg_drv_default_handler, - [NET_RPMSG_IFDOWN] = net_rpmsg_drv_default_handler, + [NET_RPMSG_IFUP] = net_rpmsg_drv_ifup_handler, + [NET_RPMSG_IFDOWN] = net_rpmsg_drv_ifdown_handler, [NET_RPMSG_ADDMCAST] = net_rpmsg_drv_default_handler, [NET_RPMSG_RMMCAST] = net_rpmsg_drv_default_handler, [NET_RPMSG_DEVIOCTL] = net_rpmsg_drv_default_handler, @@ -281,6 +292,42 @@ static int net_rpmsg_drv_default_handler(FAR struct rpmsg_endpoint *ept, return 0; } +static int net_rpmsg_drv_ifup_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct net_rpmsg_drv_s *priv = priv_; + FAR struct net_rpmsg_header_s *header = data; + + netdev_lower_carrier_on(&priv->dev); + if (priv->cb != NULL) + { + priv->cb(&priv->dev, NET_RPMSG_EVENT_CARRIER_ON); + } + + rpmsg_send_response(ept, header, sizeof(*header), 0); + + return 0; +} + +static int net_rpmsg_drv_ifdown_handler(FAR struct rpmsg_endpoint *ept, + FAR void *data, size_t len, + uint32_t src, FAR void *priv_) +{ + FAR struct net_rpmsg_drv_s *priv = priv_; + FAR struct net_rpmsg_header_s *header = data; + + netdev_lower_carrier_off(&priv->dev); + if (priv->cb != NULL) + { + priv->cb(&priv->dev, NET_RPMSG_EVENT_CARRIER_OFF); + } + + rpmsg_send_response(ept, header, sizeof(*header), 0); + + return 0; +} + static int net_rpmsg_drv_sockioctl_task(int argc, FAR char *argv[]) { FAR struct net_rpmsg_ioctl_s *msg; @@ -438,6 +485,44 @@ static int net_rpmsg_drv_default_response(FAR struct rpmsg_endpoint *ept, return 0; } +/**************************************************************************** + * Name: net_rpmsg_drv_ept_release + ****************************************************************************/ + +static void net_rpmsg_drv_ept_release(FAR struct rpmsg_endpoint *ept) +{ + FAR struct net_rpmsg_drv_s *priv = ept->priv; + + netdev_lower_carrier_off(&priv->dev); + rpmsg_wait(&priv->ept, &priv->wait); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_ns_bound + * + * Description: + * Rpmsg device end point service bound callback function , called when + * remote end point address is received. + * + * Parameters: + * ept - The rpmsg-device end point + * + * Returned Values: + * None + * + ****************************************************************************/ + +static void net_rpmsg_drv_ns_bound(FAR struct rpmsg_endpoint *ept) +{ + FAR struct net_rpmsg_drv_s *priv = ept->priv; + + rpmsg_post(&priv->ept, &priv->wait); +} + +/**************************************************************************** + * Name: net_rpmsg_drv_device_created + ****************************************************************************/ + static void net_rpmsg_drv_device_created(FAR struct rpmsg_device *rdev, FAR void *priv_) { @@ -448,7 +533,7 @@ static void net_rpmsg_drv_device_created(FAR struct rpmsg_device *rdev, { priv->ept.priv = priv; snprintf(eptname, sizeof(eptname), - NET_RPMSG_EPT_NAME, priv->devname); + NET_RPMSG_EPT_PREFIX "%s", priv->dev.netdev.d_ifname); rpmsg_create_ept(&priv->ept, rdev, eptname, RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, @@ -456,6 +541,10 @@ static void net_rpmsg_drv_device_created(FAR struct rpmsg_device *rdev, } } +/**************************************************************************** + * Name: net_rpmsg_drv_device_destroy + ****************************************************************************/ + static void net_rpmsg_drv_device_destroy(FAR struct rpmsg_device *rdev, FAR void *priv_) { @@ -496,8 +585,16 @@ static int net_rpmsg_drv_send_recv(FAR struct netdev_lowerhalf_s *dev, container_of(dev, struct net_rpmsg_drv_s, dev); FAR struct net_rpmsg_header_s *header = header_; FAR struct net_rpmsg_drv_cookie_s cookie; + int sval = 0; int ret; + nxsem_get_value(&priv->wait, &sval); + if (sval <= 0) + { + rpmsg_wait(&priv->ept, &priv->wait); + rpmsg_post(&priv->ept, &priv->wait); + } + nxsem_init(&cookie.sem, 0, 0); cookie.header = header; @@ -540,6 +637,8 @@ out: static int net_rpmsg_drv_ifup(FAR struct netdev_lowerhalf_s *dev) { + FAR struct net_rpmsg_drv_s *priv = + container_of(dev, struct net_rpmsg_drv_s, dev); struct net_rpmsg_ifup_s msg = { }; @@ -639,6 +738,11 @@ static int net_rpmsg_drv_ifup(FAR struct netdev_lowerhalf_s *dev) # endif #endif + if (priv->cb != NULL) + { + priv->cb(dev, NET_RPMSG_EVENT_IF_UP); + } + return OK; } @@ -661,14 +765,26 @@ static int net_rpmsg_drv_ifup(FAR struct netdev_lowerhalf_s *dev) static int net_rpmsg_drv_ifdown(FAR struct netdev_lowerhalf_s *dev) { - FAR struct net_rpmsg_ifdown_s msg; + FAR struct net_rpmsg_drv_s *priv = + container_of(dev, struct net_rpmsg_drv_s, dev); + struct net_rpmsg_ifdown_s msg = + { + }; + + int ret; - /* Put the EMAC in its reset, non-operational state. This should be - * a known configuration that will guarantee the net_rpmsg_drv_ifup() - * always successfully brings the interface back up. - */ + ret = net_rpmsg_drv_send_recv(dev, &msg, NET_RPMSG_IFDOWN, sizeof(msg)); + if (ret < 0) + { + return ret; + } - return net_rpmsg_drv_send_recv(dev, &msg, NET_RPMSG_IFDOWN, sizeof(msg)); + if (priv->cb != NULL) + { + priv->cb(dev, NET_RPMSG_EVENT_IF_DOWN); + } + + return ret; } /**************************************************************************** @@ -783,6 +899,45 @@ static int net_rpmsg_drv_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, } #endif +/**************************************************************************** + * Name: net_rpmsg_drv_alloc + ****************************************************************************/ + +static FAR struct net_rpmsg_drv_s * +net_rpmsg_drv_alloc(FAR const char *devname, enum net_lltype_e lltype) +{ + FAR struct net_rpmsg_drv_s *priv = kmm_zalloc(sizeof(*priv)); + FAR struct netdev_lowerhalf_s *netdev; + + if (!priv) + { + return NULL; + } + + netdev = &priv->dev; + netdev->quota[NETPKT_RX] = CONFIG_IOB_NBUFFERS / + NET_RPMSG_DRV_MAX_NIOB / 4; + netdev->quota[NETPKT_TX] = 1; + netdev->ops = &g_net_rpmsg_drv_ops; + + priv->ept.priv = priv; + priv->ept.release_cb = net_rpmsg_drv_ept_release; + priv->ept.ns_bound_cb = net_rpmsg_drv_ns_bound; + + nxsem_init(&priv->wait, 0, 0); + + /* Init a random MAC address, the caller can override it. */ + + arc4random_buf(&netdev->netdev.d_mac.ether.ether_addr_octet, + sizeof(netdev->netdev.d_mac.ether.ether_addr_octet)); + + strlcpy(netdev->netdev.d_ifname, devname, IFNAMSIZ); + + netdev_lower_register(netdev, lltype); + + return priv; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -791,52 +946,44 @@ static int net_rpmsg_drv_ioctl(FAR struct netdev_lowerhalf_s *dev, int cmd, * Name: net_rpmsg_drv_init * * Description: - * Initialize the net rpmsg driver + * Allocate a new network device instance for the RPMSG network and + * register it with the network device manager. This is the client side of + * the RPMSG driver. The RPMSG driver is the server side of the driver. * * Parameters: - * name - Specify the netdev name - * lltype - Identify the link type + * cpuname - Remote CPU name + * devname - Local and remote network device name + * lltype - Link layer type * * Returned Value: - * OK on success; Negated errno on failure. - * - * Assumptions: - * Called early in initialization before multi-tasking is initiated. + * A pointer to the allocated network device instance. NULL is returned on + * failure. * ****************************************************************************/ -int net_rpmsg_drv_init(FAR const char *cpuname, - FAR const char *devname, - enum net_lltype_e lltype) +FAR struct netdev_lowerhalf_s * +net_rpmsg_drv_init(FAR const char *cpuname, FAR const char *devname, + enum net_lltype_e lltype) { - FAR struct net_rpmsg_drv_s *priv; + FAR struct net_rpmsg_drv_s *drv; FAR struct netdev_lowerhalf_s *dev; int ret; /* Allocate the interface structure */ - priv = kmm_zalloc(sizeof(*priv)); - if (priv == NULL) + if (!devname || !cpuname || + !(drv = net_rpmsg_drv_alloc(devname, lltype))) { - return -ENOMEM; + return NULL; } - dev = &priv->dev; - - priv->cpuname = cpuname; - priv->devname = devname; - - /* Initialize the driver structure */ + strlcpy(drv->cpuname, cpuname, RPMSG_NAME_SIZE); - strlcpy(dev->netdev.d_ifname, devname, IFNAMSIZ); - - dev->quota[NETPKT_RX] = CONFIG_IOB_NBUFFERS / NET_RPMSG_DRV_MAX_NIOB / 4; - dev->quota[NETPKT_TX] = 1; - dev->ops = &g_net_rpmsg_drv_ops; + dev = &drv->dev; /* Register the device with the openamp */ - ret = rpmsg_register_callback(priv, + ret = rpmsg_register_callback(drv, net_rpmsg_drv_device_created, net_rpmsg_drv_device_destroy, NULL, @@ -844,22 +991,37 @@ int net_rpmsg_drv_init(FAR const char *cpuname, if (ret < 0) { - kmm_free(priv); - return ret; + netdev_lower_unregister(dev); + nxsem_destroy(&drv->wait); + kmm_free(drv); + return NULL; } - /* Register the device with the OS so that socket IOCTLs can be performed */ + return dev; +} - ret = netdev_lower_register(dev, lltype); - if (ret < 0) - { - rpmsg_unregister_callback(dev, - net_rpmsg_drv_device_created, - net_rpmsg_drv_device_destroy, - NULL, - NULL); - kmm_free(priv); - } +/**************************************************************************** + * Name: net_rpmsg_drv_priv + ****************************************************************************/ - return ret; +FAR void *net_rpmsg_drv_priv(FAR struct netdev_lowerhalf_s *dev) +{ + FAR struct net_rpmsg_drv_s *priv = + container_of(dev, struct net_rpmsg_drv_s, dev); + + return priv->priv; +} + +/**************************************************************************** + * Name: net_rpmsg_drv_set_callback + ****************************************************************************/ + +void net_rpmsg_drv_set_callback(FAR struct netdev_lowerhalf_s *dev, + net_rpmsg_drv_cb_t cb, FAR void *priv) +{ + FAR struct net_rpmsg_drv_s *priv = + container_of(dev, struct net_rpmsg_drv_s, dev); + + priv->cb = cb; + priv->priv = priv; } diff --git a/include/nuttx/net/rpmsg.h b/include/nuttx/net/rpmsg.h index 1f24537c566..8f18b9ffe15 100644 --- a/include/nuttx/net/rpmsg.h +++ b/include/nuttx/net/rpmsg.h @@ -33,7 +33,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define NET_RPMSG_EPT_NAME "rpmsg-%s" +#define NET_RPMSG_EPT_PREFIX "rpmsg-net-" #define NET_RPMSG_IFUP 0 /* IP-->LINK */ #define NET_RPMSG_IFDOWN 1 /* IP-->LINK */ diff --git a/include/nuttx/net/rpmsgdrv.h b/include/nuttx/net/rpmsgdrv.h index 061c0191b25..032038758c9 100644 --- a/include/nuttx/net/rpmsgdrv.h +++ b/include/nuttx/net/rpmsgdrv.h @@ -28,18 +28,94 @@ ****************************************************************************/ #include <nuttx/config.h> -#include <nuttx/net/net.h> +#include <nuttx/net/netdev_lowerhalf.h> /**************************************************************************** - * Public Function Prototypes + * Pre-processor Definitions ****************************************************************************/ #ifdef CONFIG_NET_RPMSG_DRV -int net_rpmsg_drv_init(FAR const char *cpuname, - FAR const char *devname, - enum net_lltype_e lltype); + +#define NET_RPMSG_EVENT_IF_UP 1 +#define NET_RPMSG_EVENT_IF_DOWN 2 +#define NET_RPMSG_EVENT_CARRIER_ON 3 +#define NET_RPMSG_EVENT_CARRIER_OFF 4 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef CODE void (*net_rpmsg_drv_cb_t)(FAR struct netdev_lowerhalf_s *dev, + int event); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ #else -#define net_rpmsg_drv_init(cpuname, devname, lltye) +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: net_rpmsg_drv_init + * + * Description: + * Allocate a new network device instance for the RPMSG network and + * register it with the network device manager. This is the client side of + * the RPMSG driver. The RPMSG driver is the server side of the driver. + * + * Input Parameters: + * cpuname - Remote CPU name + * devname - Local and remote network device name + * lltype - Link layer type + * priv - Reference to the caller's private data + * + * Returned Value: + * A pointer to the allocated network device instance. NULL is returned on + * failure. + * + ****************************************************************************/ + +FAR struct netdev_lowerhalf_s * +net_rpmsg_drv_init(FAR const char *cpuname, FAR const char *devname, + enum net_lltype_e lltype); + +/**************************************************************************** + * Name: net_rpmsg_drv_priv + * + * Description: + * Get the private data associated with the network device instance. + * + * Input Parameters: + * dev - Reference to the network device instance. + * + ****************************************************************************/ + +FAR void *net_rpmsg_drv_priv(FAR struct netdev_lowerhalf_s *dev); + +/**************************************************************************** + * Name: net_rpmsg_drv_set_callback + * + * Description: + * Set the callback function for the network device instance. + * + * Input Parameters: + * dev - Reference to the network device instance. + * cb - Callback function to be set. + * + ****************************************************************************/ + +void net_rpmsg_drv_set_callback(FAR struct netdev_lowerhalf_s *dev, + net_rpmsg_drv_cb_t cb, FAR void *priv); + +#undef EXTERN +#ifdef __cplusplus +} #endif +#endif #endif /* __INCLUDE_NUTTX_NET_RPMSGDRV_H */
