ab47465dd5
Add get_local_cpuname to the rpmsg framework ops to support communicate with the same remote core with multi rpmsg transport. Some rpmsg services will send local cpu name to remote core and then let remote core to connect local core by using this cpu name, when there are multi rpmsg channels with same remote core, the remote core may connect to incorrect core, so use the error rpmsg channel. For example, there are two rpmsg channels between ap and audio: ap core audio core [ap1] <-- rpmsg virtio1 --> [audio1] [ap2] <-- rpmsg virtio2 --> [audio2] When we want to use the rpmsg virtio1 to communicate, ap core may send local cpuname "ap2" to audio, so the audio core use remote cpu "ap2" to connect with ap, and resulting in the use of incorrect rpmsg channel. Signed-off-by: Bowen Wang <wangbowen6@xiaomi.com>
736 lines
22 KiB
C
736 lines
22 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 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)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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_cb
|
|
*
|
|
* Description:
|
|
* This function is used to receive sync message from router core,
|
|
* and initialize the router rpmsg 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;
|
|
FAR struct rpmsg_device *rdev;
|
|
char name[32];
|
|
int ret;
|
|
|
|
edge = kmm_zalloc(sizeof(*edge));
|
|
if (!edge)
|
|
{
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Initialize router device */
|
|
|
|
strlcpy(edge->remotecpu, ept->name + RPMSG_ROUTER_NAME_LEN,
|
|
sizeof(edge->remotecpu));
|
|
edge->rx_len = msg->rx_len;
|
|
edge->tx_len = msg->tx_len;
|
|
edge->hubdev = ept->rdev;
|
|
ept->priv = edge;
|
|
|
|
/* 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(name, sizeof(name), "/dev/rpmsg/%s", edge->remotecpu);
|
|
ret = rpmsg_register(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 0;
|
|
|
|
unregister:
|
|
rpmsg_unregister(name, &edge->rpmsg);
|
|
free:
|
|
kmm_free(edge);
|
|
ept->priv = NULL;
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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)
|
|
{
|
|
kmm_free(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);
|
|
}
|