968da8b781
use cmd to notify the other cpu to destroy router edge device, and dont destroy the other cpu's "router:ept" Signed-off-by: yintao <yintao@xiaomi.com>
811 lines
24 KiB
C
811 lines
24 KiB
C
/****************************************************************************
|
|
* drivers/rpmsg/rpmsg_router_edge.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <debug.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
|
|
#include <nuttx/kmalloc.h>
|
|
#include <rpmsg/rpmsg_internal.h>
|
|
|
|
#include "rpmsg_router.h"
|
|
|
|
/****************************************************************************
|
|
* Rpmsg-router Model:
|
|
*
|
|
* +------+ +------+ +------+
|
|
* | edge |<----->| hub |<----->| edge |
|
|
* +------+ +------+ +------+
|
|
*
|
|
* Description:
|
|
* edge CPUs (edge) are physically linked to the central router cpu (hub),
|
|
* edge CPUs' communication reply on hub cpu message forwarding.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define rpmsg_router_edge_from_rdev(d) \
|
|
metal_container_of(d, struct rpmsg_router_edge_s, rdev)
|
|
|
|
#define RPMSG_ROUTER_USER_NAME_SIZE \
|
|
(RPMSG_NAME_SIZE - RPMSG_ROUTER_NAME_PREFIX_LEN - RPMSG_ROUTER_CPUNAME_LEN)
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
struct rpmsg_router_edge_s
|
|
{
|
|
struct rpmsg_s rpmsg;
|
|
struct rpmsg_device rdev;
|
|
struct rpmsg_device *hubdev;
|
|
char name[RPMSG_NAME_SIZE];
|
|
char localcpu[RPMSG_ROUTER_CPUNAME_LEN];
|
|
char remotecpu[RPMSG_ROUTER_CPUNAME_LEN];
|
|
|
|
/* Tx/Rx buffer size */
|
|
|
|
uint32_t tx_len;
|
|
uint32_t rx_len;
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
static FAR const char *
|
|
rpmsg_router_edge_get_local_cpuname(FAR struct rpmsg_s *rpmsg);
|
|
static FAR const char *
|
|
rpmsg_router_edge_get_cpuname(FAR struct rpmsg_s *rpmsg);
|
|
static int rpmsg_router_edge_get_tx_buffer_size(FAR struct rpmsg_s *rpmsg);
|
|
static int rpmsg_router_edge_get_rx_buffer_size(FAR struct rpmsg_s *rpmsg);
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static const struct rpmsg_ops_s g_rpmsg_router_edge_ops =
|
|
{
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
rpmsg_router_edge_get_local_cpuname,
|
|
rpmsg_router_edge_get_cpuname,
|
|
rpmsg_router_edge_get_tx_buffer_size,
|
|
rpmsg_router_edge_get_rx_buffer_size,
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_get_local_cpuname
|
|
****************************************************************************/
|
|
|
|
static FAR const char *
|
|
rpmsg_router_edge_get_local_cpuname(FAR struct rpmsg_s *rpmsg)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
return edge->localcpu;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_get_cpuname
|
|
****************************************************************************/
|
|
|
|
static FAR const char *
|
|
rpmsg_router_edge_get_cpuname(FAR struct rpmsg_s *rpmsg)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
return edge->remotecpu;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_get_tx_buffer_size
|
|
****************************************************************************/
|
|
|
|
static int rpmsg_router_edge_get_tx_buffer_size(FAR struct rpmsg_s *rpmsg)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
return edge->tx_len;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_get_rx_buffer_size
|
|
****************************************************************************/
|
|
|
|
static int rpmsg_router_edge_get_rx_buffer_size(FAR struct rpmsg_s *rpmsg)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge =
|
|
(FAR struct rpmsg_router_edge_s *)rpmsg;
|
|
|
|
return edge->rx_len;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_get_tx_payload_buffer
|
|
****************************************************************************/
|
|
|
|
static FAR void *
|
|
rpmsg_router_edge_get_tx_payload_buffer(FAR struct rpmsg_device *rdev,
|
|
FAR uint32_t *len, int wait)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
|
FAR void *buf;
|
|
|
|
if (!hubdev->ops.get_tx_payload_buffer)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
buf = hubdev->ops.get_tx_payload_buffer(hubdev, len, wait);
|
|
*len = edge->tx_len;
|
|
return buf;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_hold_rx_buffer
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_edge_hold_rx_buffer(FAR struct rpmsg_device *rdev,
|
|
FAR void *rxbuf)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
if (!hubdev->ops.hold_rx_buffer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
hubdev->ops.hold_rx_buffer(hubdev, rxbuf);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_release_rx_buffer
|
|
****************************************************************************/
|
|
|
|
static void
|
|
rpmsg_router_edge_release_rx_buffer(FAR struct rpmsg_device *rdev,
|
|
FAR void *rxbuf)
|
|
{
|
|
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
if (!hubdev->ops.release_rx_buffer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
hubdev->ops.release_rx_buffer(hubdev, rxbuf);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_release_tx_buffer
|
|
****************************************************************************/
|
|
|
|
static int rpmsg_router_edge_release_tx_buffer(FAR struct rpmsg_device *rdev,
|
|
FAR void *txbuf)
|
|
{
|
|
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
if (!hubdev->ops.release_tx_buffer)
|
|
{
|
|
return RPMSG_ERR_PERM;
|
|
}
|
|
|
|
return hubdev->ops.release_tx_buffer(hubdev, txbuf);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_send_nocopy
|
|
****************************************************************************/
|
|
|
|
static int rpmsg_router_edge_send_nocopy(FAR struct rpmsg_device *rdev,
|
|
uint32_t src, uint32_t dst,
|
|
FAR const void *data, int len)
|
|
{
|
|
struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
struct rpmsg_device *hubdev = edge->hubdev;
|
|
|
|
if (!hubdev->ops.send_offchannel_nocopy)
|
|
{
|
|
return RPMSG_ERR_PARAM;
|
|
}
|
|
|
|
return hubdev->ops.send_offchannel_nocopy(hubdev, src, dst, data, len);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_cb
|
|
*
|
|
* Description:
|
|
* This is the callback function for edge core.
|
|
* It will receive data from real rpmsg channel by ept(r:cpu:name),
|
|
* and find the corresponding user ept, then processing data through
|
|
* the user ept callback.
|
|
*
|
|
* Parameters:
|
|
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
|
* data - received data
|
|
* len - received data length
|
|
* src - source address
|
|
* priv - save user rpmsg_endpoint generally
|
|
*
|
|
* Returned Values:
|
|
* 0 on success; A negated errno value is returned on any failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int rpmsg_router_edge_cb(FAR struct rpmsg_endpoint *ept,
|
|
FAR void *data, size_t len,
|
|
uint32_t src, FAR void *priv)
|
|
{
|
|
FAR struct rpmsg_endpoint *usr_ept = priv;
|
|
|
|
if (!usr_ept)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* Processing data through the user ept callback */
|
|
|
|
return usr_ept->cb(usr_ept, data, len, src, usr_ept->priv);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_bound
|
|
*
|
|
* Description:
|
|
* This is the callback function for edge core.
|
|
* It will be called when the edge core is bound to the router core
|
|
* by r:cpu:name, save the destination address of the edge core, and
|
|
* call the bound function of the user endpoint.
|
|
*
|
|
* Parameters:
|
|
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_edge_bound(FAR struct rpmsg_endpoint *ept)
|
|
{
|
|
FAR struct rpmsg_endpoint *usr_ept = ept->priv;
|
|
|
|
if (!usr_ept)
|
|
{
|
|
rpmsgerr("Try to get user ept failed.\n");
|
|
return;
|
|
}
|
|
|
|
usr_ept->dest_addr = ept->dest_addr;
|
|
if (usr_ept->ns_bound_cb)
|
|
{
|
|
usr_ept->ns_bound_cb(usr_ept);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_unbind
|
|
*
|
|
* Description:
|
|
* This is the unbind callback function for edge core.
|
|
*
|
|
* Parameters:
|
|
* ept - rpmsg_endpoint for communicating with router core (r:cpu:name)
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_edge_unbind(FAR struct rpmsg_endpoint *ept)
|
|
{
|
|
FAR struct rpmsg_endpoint *usr_ept = ept->priv;
|
|
|
|
if (!usr_ept)
|
|
{
|
|
rpmsgerr("Try to get user ept failed.\n");
|
|
return;
|
|
}
|
|
|
|
if (usr_ept->ns_unbind_cb)
|
|
{
|
|
usr_ept->ns_unbind_cb(usr_ept);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_release
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_edge_release(FAR struct rpmsg_endpoint *ept)
|
|
{
|
|
kmm_free(ept);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_send_offchannel_raw
|
|
*
|
|
* Description:
|
|
* This function sends normal rpmsg message or ns message to remote device.
|
|
* If the destination address is RPMSG_NS_EPT_ADDR, it will create a new
|
|
* endpoint(r:cpu:name) for real communication, and save the user endpoint
|
|
* information in the private field of the new endpoint.
|
|
*
|
|
* Parameters:
|
|
* rdev - rpmsg_device for router core
|
|
* src - source address
|
|
* dst - destination address
|
|
* data - data to send
|
|
* len - data length
|
|
* wait - boolean, wait or not for buffer to become available
|
|
*
|
|
* Returned Values:
|
|
* size of data sent or negative value for failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int
|
|
rpmsg_router_edge_send_offchannel_raw(FAR struct rpmsg_device *rdev,
|
|
uint32_t src, uint32_t dst,
|
|
FAR const void *data,
|
|
int len, int wait)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge = rpmsg_router_edge_from_rdev(rdev);
|
|
FAR struct rpmsg_ns_msg *ns_msg = (FAR struct rpmsg_ns_msg *)data;
|
|
FAR struct rpmsg_device *hubdev = edge->hubdev;
|
|
FAR struct rpmsg_endpoint *usr_ept;
|
|
FAR struct rpmsg_endpoint *ept;
|
|
char name[RPMSG_ROUTER_USER_NAME_SIZE];
|
|
int ret;
|
|
|
|
/* Send normal rpmsg "message" to remote device */
|
|
|
|
if (dst != RPMSG_NS_EPT_ADDR)
|
|
{
|
|
if (!hubdev->ops.send_offchannel_raw)
|
|
{
|
|
return RPMSG_ERR_PARAM;
|
|
}
|
|
|
|
return hubdev->ops.send_offchannel_raw(hubdev, src,
|
|
dst, data, len, wait);
|
|
}
|
|
|
|
/* Try to get user ept firstly */
|
|
|
|
metal_mutex_acquire(&rdev->lock);
|
|
usr_ept = rpmsg_get_endpoint(rdev, ns_msg->name, src, dst);
|
|
metal_mutex_release(&rdev->lock);
|
|
if (!usr_ept)
|
|
{
|
|
rpmsgerr("Try to get user ept failed.\n");
|
|
return RPMSG_ERR_PARAM;
|
|
}
|
|
|
|
/* Set hub endpoint name(r:cpu:name) for real communication */
|
|
|
|
strlcpy(name, ns_msg->name, sizeof(name));
|
|
snprintf(ns_msg->name, sizeof(ns_msg->name),
|
|
RPMSG_ROUTER_NAME_PREFIX"%s:%s", edge->remotecpu, name);
|
|
|
|
if (ns_msg->flags == RPMSG_NS_DESTROY)
|
|
{
|
|
/* Processing RPMSG_NS_DESTROY message */
|
|
|
|
metal_mutex_acquire(&hubdev->lock);
|
|
ept = rpmsg_get_endpoint(hubdev, ns_msg->name,
|
|
RPMSG_ADDR_ANY, usr_ept->dest_addr);
|
|
metal_mutex_release(&hubdev->lock);
|
|
if (!ept)
|
|
{
|
|
rpmsgerr("Try to get router endpoint (r:ept) failed.\n");
|
|
return RPMSG_ERR_PARAM;
|
|
}
|
|
|
|
/* Destroy endpoint(r:cpu:name) of real communication */
|
|
|
|
rpmsg_destroy_ept(ept);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
/* Processing RPMSG_NS_CREATE or RPMSG_NS_CREATE_ACK message */
|
|
|
|
ept = kmm_zalloc(sizeof(*ept));
|
|
if (!ept)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Save user endpoint */
|
|
|
|
ept->priv = usr_ept;
|
|
ept->ns_bound_cb = rpmsg_router_edge_bound;
|
|
ept->release_cb = rpmsg_router_edge_release;
|
|
|
|
/* Create endpoint (r:cpu:name) for real communication */
|
|
|
|
ret = rpmsg_create_ept(ept, hubdev, ns_msg->name,
|
|
RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
|
|
rpmsg_router_edge_cb,
|
|
rpmsg_router_edge_unbind);
|
|
if (ret < 0)
|
|
{
|
|
rpmsgerr("Create router endpoint failed: %d\n", ret);
|
|
kmm_free(ept);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_match
|
|
*
|
|
* Description:
|
|
* This function is used to match the edge core device.
|
|
* rpmsg_router_edge_bind will be called if the device is matched.
|
|
*
|
|
* Parameters:
|
|
* rdev - real rpmsg device
|
|
* priv - rpmsg router device for edge core
|
|
* name - endpoint name (r:cpu:name)
|
|
* dest - destination address
|
|
*
|
|
* Returned Values:
|
|
* true on success; false on failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static bool rpmsg_router_edge_match(FAR struct rpmsg_device *rdev,
|
|
FAR void *priv, FAR const char *name,
|
|
uint32_t dest)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge = priv;
|
|
|
|
if (strncmp(name, RPMSG_ROUTER_NAME_PREFIX, RPMSG_ROUTER_NAME_PREFIX_LEN))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return !strncmp(name + RPMSG_ROUTER_NAME_PREFIX_LEN, edge->remotecpu,
|
|
strlen(edge->remotecpu));
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_bind
|
|
*
|
|
* Description:
|
|
* This function is used to bind the edge core device.
|
|
* It will try to find rpmsg_user_ns_bind_cb by user ept name.
|
|
*
|
|
* Parameters:
|
|
* rdev - real rpmsg device
|
|
* priv - rpmsg router device for edge core
|
|
* name - endpoint name (r:cpu:name)
|
|
* dest - destination address
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_edge_bind(FAR struct rpmsg_device *rdev,
|
|
FAR void *priv, FAR const char *name,
|
|
uint32_t dest)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge = priv;
|
|
FAR struct rpmsg_device *edgedev = &edge->rdev;
|
|
|
|
edgedev->ns_bind_cb(edgedev,
|
|
name + RPMSG_ROUTER_NAME_PREFIX_LEN +
|
|
strlen(edge->remotecpu) + 1, dest);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_destroy
|
|
*
|
|
* Description:
|
|
* This function is used to destroy the edge core device.
|
|
*
|
|
* Parameters:
|
|
* edge - rpmsg router edge device
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_edge_destroy(FAR struct rpmsg_router_edge_s *edge)
|
|
{
|
|
rpmsg_unregister_callback(edge, NULL, NULL,
|
|
rpmsg_router_edge_match,
|
|
rpmsg_router_edge_bind);
|
|
rpmsg_unregister(edge->name, &edge->rpmsg);
|
|
rpmsg_device_destory(&edge->rpmsg);
|
|
kmm_free(edge);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_create
|
|
*
|
|
* Description:
|
|
* This function is used to create the edge core device.
|
|
*
|
|
* Parameters:
|
|
* hubdev - rpmsg device for router hub
|
|
* msg - sync message from router hub
|
|
* remotecpu - remote edge cpu name
|
|
*
|
|
* Returned Values:
|
|
* edge device on success; NULL on failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static FAR struct rpmsg_router_edge_s *
|
|
rpmsg_router_edge_create(FAR struct rpmsg_device *hubdev,
|
|
FAR struct rpmsg_router_s *msg,
|
|
FAR const char *remotecpu)
|
|
{
|
|
FAR struct rpmsg_router_edge_s *edge;
|
|
FAR struct rpmsg_device *rdev;
|
|
int ret;
|
|
|
|
/* Create the router edge device */
|
|
|
|
edge = kmm_zalloc(sizeof(*edge));
|
|
if (!edge)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
strlcpy(edge->remotecpu, remotecpu, sizeof(edge->remotecpu));
|
|
strlcpy(edge->localcpu, msg->cpuname, sizeof(edge->localcpu));
|
|
edge->rx_len = msg->rx_len;
|
|
edge->tx_len = msg->tx_len;
|
|
edge->hubdev = hubdev;
|
|
|
|
/* Initialize router rpmsg device */
|
|
|
|
rdev = &edge->rdev;
|
|
metal_mutex_init(&rdev->lock);
|
|
rdev->ns_bind_cb = rpmsg_ns_bind;
|
|
rdev->ns_unbind_cb = rpmsg_ns_unbind;
|
|
rdev->ops.hold_rx_buffer = rpmsg_router_edge_hold_rx_buffer;
|
|
rdev->ops.release_rx_buffer = rpmsg_router_edge_release_rx_buffer;
|
|
rdev->ops.release_tx_buffer = rpmsg_router_edge_release_tx_buffer;
|
|
rdev->ops.send_offchannel_nocopy = rpmsg_router_edge_send_nocopy;
|
|
rdev->ops.send_offchannel_raw = rpmsg_router_edge_send_offchannel_raw;
|
|
rdev->ops.get_tx_payload_buffer = rpmsg_router_edge_get_tx_payload_buffer;
|
|
|
|
metal_list_init(&rdev->endpoints);
|
|
rdev->support_ack = true;
|
|
rdev->support_ns = true;
|
|
|
|
/* Register rpmsg for edge core */
|
|
|
|
snprintf(edge->name, sizeof(edge->name), "/dev/rpmsg/%s", edge->remotecpu);
|
|
ret = rpmsg_register(edge->name, &edge->rpmsg, &g_rpmsg_router_edge_ops);
|
|
if (ret < 0)
|
|
{
|
|
rpmsgerr("rpmsg_register failed: %d\n", ret);
|
|
goto free;
|
|
}
|
|
|
|
/* Register callback for edge core */
|
|
|
|
ret = rpmsg_register_callback(edge, NULL, NULL,
|
|
rpmsg_router_edge_match,
|
|
rpmsg_router_edge_bind);
|
|
|
|
if (ret < 0)
|
|
{
|
|
rpmsgerr("Register rpmsg callback failed: %d\n", ret);
|
|
goto unregister;
|
|
}
|
|
|
|
/* Broadcast device_created to all registers */
|
|
|
|
rpmsg_device_created(&edge->rpmsg);
|
|
return edge;
|
|
|
|
unregister:
|
|
rpmsg_unregister(edge->name, &edge->rpmsg);
|
|
free:
|
|
kmm_free(edge);
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_cb
|
|
*
|
|
* Description:
|
|
* This function is used to receive sync message from router core,
|
|
* and create or destroy the edge core device.
|
|
*
|
|
* Parameters:
|
|
* ept - endpoint for synchronizing ready messages
|
|
* data - received data
|
|
* len - received data length
|
|
* src - source address
|
|
* priv - private data
|
|
*
|
|
* Returned Values:
|
|
* 0 on success; A negated errno value is returned on any failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int rpmsg_router_cb(FAR struct rpmsg_endpoint *ept,
|
|
FAR void *data, size_t len,
|
|
uint32_t src, FAR void *priv)
|
|
{
|
|
FAR struct rpmsg_router_s *msg = data;
|
|
FAR struct rpmsg_router_edge_s *edge;
|
|
|
|
/* Destroy the router edge device */
|
|
|
|
if (msg->cmd == RPMSG_ROUTER_DESTROY)
|
|
{
|
|
edge = ept->priv;
|
|
|
|
if (edge)
|
|
{
|
|
rpmsg_router_edge_destroy(edge);
|
|
ept->priv = NULL;
|
|
return 0;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Create the router edge device */
|
|
|
|
edge = rpmsg_router_edge_create(ept->rdev, msg,
|
|
ept->name + RPMSG_ROUTER_NAME_LEN);
|
|
if (!edge)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
|
|
ept->priv = edge;
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_unbind
|
|
*
|
|
* Description:
|
|
* This function is used to destroy the sync endpoint
|
|
* when another edge core is disconnected.
|
|
*
|
|
* Parameters:
|
|
* ept - rpmsg endpoint for synchronizing message.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_unbind(FAR struct rpmsg_endpoint *ept)
|
|
{
|
|
struct rpmsg_router_edge_s *edge = ept->priv;
|
|
|
|
if (edge)
|
|
{
|
|
rpmsg_router_edge_destroy(edge);
|
|
ept->priv = NULL;
|
|
}
|
|
|
|
rpmsg_destroy_ept(ept);
|
|
kmm_free(ept);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_match
|
|
*
|
|
* Description:
|
|
* This function is used to match the endpoint for
|
|
* synchronizing ready messages.
|
|
*
|
|
* Parameters:
|
|
* rdev - real rpmsg device
|
|
* priv - rpmsg_router_priv
|
|
* name - endpoint name
|
|
* dest - destination address
|
|
*
|
|
* Returned Values:
|
|
* true on success; false on failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static bool rpmsg_router_match(FAR struct rpmsg_device *rdev, FAR void *priv,
|
|
FAR const char *name, uint32_t dest)
|
|
{
|
|
return !strncmp(name, RPMSG_ROUTER_NAME, RPMSG_ROUTER_NAME_LEN);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_bind
|
|
*
|
|
* Description:
|
|
* This function is used to bind the endpoint for
|
|
* synchronizing ready messages.
|
|
*
|
|
* Parameters:
|
|
* rdev - real rpmsg device
|
|
* priv - private data
|
|
* name - endpoint name
|
|
* dest - destination address
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void rpmsg_router_bind(FAR struct rpmsg_device *rdev, FAR void *priv,
|
|
FAR const char *name, uint32_t dest)
|
|
{
|
|
FAR struct rpmsg_endpoint *ept;
|
|
int ret;
|
|
|
|
ept = kmm_zalloc(sizeof(*ept));
|
|
DEBUGASSERT(ept);
|
|
|
|
ret = rpmsg_create_ept(ept, rdev, name, RPMSG_ADDR_ANY, dest,
|
|
rpmsg_router_cb, rpmsg_router_unbind);
|
|
if (ret < 0)
|
|
{
|
|
rpmsgerr("Create router endpoint failed: %d\n", ret);
|
|
kmm_free(ept);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: rpmsg_router_edge_init
|
|
*
|
|
* Description:
|
|
* This function is used to initialize the edge core.
|
|
*
|
|
* Returned Values:
|
|
* OK on success; A negated errno value is returned on any failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int rpmsg_router_edge_init(void)
|
|
{
|
|
/* Register callback for listening sync message from router hub */
|
|
|
|
return rpmsg_register_callback(NULL, NULL, NULL,
|
|
rpmsg_router_match,
|
|
rpmsg_router_bind);
|
|
}
|