summaryrefslogtreecommitdiff
path: root/components/drivers/rpmsg/rpmsg_ns.c
blob: 9383cb2fa7629ec4bb5185cbe9fec443a3c4fb58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-02-25     GuEe-GUI     the first version
 */

#include <rtthread.h>
#include <rtdevice.h>

#define DBG_TAG "rpmsg.ns"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

/*
 * Used when rt_rpmsg_create_endpoint(..., RT_NULL) (e.g. remote NS announce);
 * application traffic should be bound via a higher layer later.
 */
static rt_err_t rpmsg_ns_remote_default_rx(struct rt_rpmsg_device *rdev,
        rt_uint32_t src, void *data, rt_size_t len)
{
    LOG_D("%s: remote endpoint rx (no user cb), src=%u len=%u", rt_dm_dev_get_name(&rdev->parent), src, len);

    return RT_EOK;
}

static rt_err_t rpmsg_ns_rx_callback(struct rt_rpmsg_device *rdev,
        rt_uint32_t src, void *data, rt_size_t len)
{
    rt_err_t err = RT_EOK;
    struct rt_rpmsg_ns_msg *msg = data;
    struct rt_rpmsg_endpoint *ept;
    struct rt_rpmsg_endpoint_info info;

    if (len != sizeof(*msg))
    {
        LOG_E("Invalid MSG size = %d", len);

        return -RT_EINVAL;
    }

    /* Fixup the name */
    msg->name[RT_RPMSG_NAME_SIZE - 1] = '\0';
    rt_strncpy(info.name, msg->name, RT_RPMSG_NAME_SIZE);
    info.src = RT_RPMSG_ADDR_ANY;
    info.dst = rt_le32_to_cpu(msg->addr);

    LOG_D("%s: name: %s, src: %u, dst: %u", rt_dm_dev_get_name(&rdev->parent),
            info.name, info.src, info.dst);

    if (rt_le32_to_cpu(msg->flags) & RT_RPMSG_NS_DESTROY)
    {
        ept = rt_rpmsg_find_endpoint(rdev, &info);

        if (ept)
        {
            err = rt_rpmsg_destroy_endpoint(rdev, ept);
        }
        else
        {
            err = -RT_EEMPTY;
        }
    }
    else if (rt_le32_to_cpu(msg->flags) == RT_RPMSG_NS_CREATE)
    {
        ept = rt_rpmsg_create_endpoint(rdev, &info, RT_NULL);

        if (rt_is_err(ept))
        {
            err = rt_ptr_err(ept);
        }
    }
    else
    {
        LOG_E("Unsupported flags = %x", rt_le32_to_cpu(msg->flags));
    }

    if (err)
    {
        LOG_E("%s: name = %s, addr = %x flags = %d error = %s",
                rt_dm_dev_get_name(&rdev->parent),
                msg->name, msg->addr, msg->flags, rt_strerror(err));
    }

    return err;
}

static rt_err_t rpmsg_ns_probe(struct rt_rpmsg_device *rdev)
{
    struct rt_rpmsg_endpoint *ep;
    struct rt_rpmsg_endpoint_info info;

    rt_strncpy(info.name, "name-service", RT_RPMSG_NAME_SIZE);
    info.src = RT_RPMSG_NS_ADDR;
    info.dst = RT_RPMSG_NS_ADDR;

    ep = rt_rpmsg_create_endpoint(rdev, &info, &rpmsg_ns_rx_callback);

    return rt_is_err(ep) ? rt_ptr_err(ep) : RT_EOK;
}

static struct rt_rpmsg_device_id rpmsg_ns_ids[] =
{
    { .name = "rpmsg-name-service" },
    { /* sentinel */ }
};

static struct rt_rpmsg_driver rpmsg_ns_driver =
{
    .parent.parent =
    {
        .name = "rpmsg-ns",
    },
    .ids = rpmsg_ns_ids,

    .probe = rpmsg_ns_probe,
    .rx_callback = rpmsg_ns_remote_default_rx,
};
RT_RPMSG_DRIVER_EXPORT(rpmsg_ns_driver);