mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-09-22 03:09:16 +08:00
[dm][virtio] update virtio dm
1. support RPMsg 2. support Sound 3. fixup virtio-blk free Signed-off-by: GuEe-GUI <2991707448@qq.com>
This commit is contained in:
@@ -45,6 +45,12 @@ config RT_VIRTIO_RNG
|
||||
depends on RT_HWCRYPTO_USING_RNG
|
||||
default y
|
||||
|
||||
config RT_VIRTIO_RPMSG
|
||||
bool "VirtIO Rpmsg"
|
||||
depends on RT_USING_VIRTIO
|
||||
depends on RT_USING_RPMSG
|
||||
default y
|
||||
|
||||
config RT_VIRTIO_SCSI
|
||||
bool "VirtIO SCSI"
|
||||
depends on RT_USING_VIRTIO
|
||||
@@ -92,6 +98,12 @@ config RT_VIRTIO_CRYPTO
|
||||
depends on RT_HWCRYPTO_USING_RC4
|
||||
default y
|
||||
|
||||
config RT_VIRTIO_SOUND
|
||||
bool "VirtIO Sound"
|
||||
depends on RT_USING_VIRTIO
|
||||
depends on RT_USING_AUDIO
|
||||
default y
|
||||
|
||||
config RT_VIRTIO_SCMI
|
||||
bool "VirtIO SCMI"
|
||||
depends on RT_USING_VIRTIO
|
||||
|
||||
@@ -28,6 +28,9 @@ if GetDepend(['RT_VIRTIO_CONSOLE']) or GetDepend(['RT_VIRTIO_RPROC_SERIAL']):
|
||||
if GetDepend(['RT_VIRTIO_RNG']):
|
||||
src += ['virtio-rng.c']
|
||||
|
||||
if GetDepend(['RT_VIRTIO_RPMSG']):
|
||||
src += ['virtio-rpmsg.c']
|
||||
|
||||
if GetDepend(['RT_VIRTIO_SCSI']):
|
||||
src += ['virtio-scsi.c']
|
||||
|
||||
@@ -43,6 +46,9 @@ if GetDepend(['RT_VIRTIO_INPUT']):
|
||||
if GetDepend(['RT_VIRTIO_CRYPTO']):
|
||||
src += ['virtio-crypto.c']
|
||||
|
||||
if GetDepend(['RT_VIRTIO_SOUND']):
|
||||
src += ['virtio-sound.c']
|
||||
|
||||
if GetDepend(['RT_VIRTIO_SCMI']):
|
||||
src += ['virtio-scmi.c']
|
||||
|
||||
|
||||
@@ -257,6 +257,7 @@ static rt_err_t virtio_blk_probe(struct rt_virtio_device *vdev)
|
||||
|
||||
if ((vblk->vblk_id = rt_dm_ida_alloc(&virtio_blk_ida)) < 0)
|
||||
{
|
||||
rt_free(vblk);
|
||||
return -RT_EFULL;
|
||||
}
|
||||
|
||||
|
||||
Executable
+460
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* 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 <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "virtio.dev.rpmsg"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include "virtio_config/virtio-rpmsg.h"
|
||||
|
||||
#define QUEUE_RX _queue_rx
|
||||
#define QUEUE_TX _queue_tx
|
||||
|
||||
struct virtio_rpmsg_tx_buf
|
||||
{
|
||||
rt_uint8_t data[VIRTIO_RPMSG_MAX_BUF_SIZE];
|
||||
rt_uint32_t idx;
|
||||
};
|
||||
|
||||
struct virtio_rpmsg
|
||||
{
|
||||
struct rt_rpmsg_device parent;
|
||||
struct rt_rpmsg_device *ns;
|
||||
struct rt_virtio_device *vdev;
|
||||
|
||||
struct rt_virtqueue *vqs[2];
|
||||
struct rt_spinlock tx_lock;
|
||||
|
||||
rt_bool_t supp_ns;
|
||||
|
||||
rt_uint8_t *tx_buffer;
|
||||
struct rt_completion *tx_done;
|
||||
};
|
||||
|
||||
#define raw_to_virtio_rpmsg(raw) (raw)->priv
|
||||
|
||||
static int _queue_rx, _queue_tx;
|
||||
|
||||
static rt_err_t virtio_rpmsg_create_endpoint(struct rt_rpmsg_device *rdev,
|
||||
struct rt_rpmsg_endpoint *ept, struct rt_rpmsg_endpoint_info *info)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
rt_bool_t is_remote = info->src == RT_RPMSG_ADDR_ANY;
|
||||
struct rt_rpmsg_endpoint *target_ept;
|
||||
struct virtio_rpmsg *vrpmsg = raw_to_virtio_rpmsg(rdev);
|
||||
|
||||
ept->sysdata = (void *)(rt_ubase_t)is_remote;
|
||||
|
||||
if (is_remote)
|
||||
{
|
||||
target_ept = rt_rpmsg_find_endpoint(rdev, info);
|
||||
|
||||
if (target_ept)
|
||||
{
|
||||
LOG_E("%s: endpoint (name: %s, src: %u, dst: %u) already exist",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent),
|
||||
info->name, info->src, info->dst);
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_remote && vrpmsg->supp_ns)
|
||||
{
|
||||
struct rt_rpmsg_ns_msg ns_msg;
|
||||
|
||||
rt_memset(&ns_msg, 0, sizeof(ns_msg));
|
||||
|
||||
if (info && info->name[0])
|
||||
{
|
||||
rt_strncpy(ns_msg.name, info->name, RT_RPMSG_NAME_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_strncpy(ns_msg.name, rdev->id.name, RT_RPMSG_NAME_SIZE);
|
||||
}
|
||||
|
||||
ns_msg.addr = rt_cpu_to_le32(ept->info.src);
|
||||
ns_msg.flags = rt_cpu_to_le32(RT_RPMSG_NS_CREATE);
|
||||
|
||||
err = rt_rpmsg_sendto(ept, RT_RPMSG_NS_ADDR, &ns_msg, sizeof(ns_msg));
|
||||
|
||||
if (err)
|
||||
{
|
||||
LOG_E("%s: Notify remote error = %s",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent), rt_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_rpmsg_destroy_endpoint(struct rt_rpmsg_device *rdev,
|
||||
struct rt_rpmsg_endpoint *ept)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
rt_bool_t is_remote = !!ept->sysdata;
|
||||
struct virtio_rpmsg *vrpmsg = raw_to_virtio_rpmsg(rdev);
|
||||
|
||||
if (!is_remote && vrpmsg->supp_ns)
|
||||
{
|
||||
struct rt_rpmsg_ns_msg ns_msg;
|
||||
|
||||
rt_memset(&ns_msg, 0, sizeof(ns_msg));
|
||||
|
||||
if (ept->info.name[0])
|
||||
{
|
||||
rt_strncpy(ns_msg.name, ept->info.name, RT_RPMSG_NAME_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_strncpy(ns_msg.name, rdev->id.name, RT_RPMSG_NAME_SIZE);
|
||||
}
|
||||
|
||||
ns_msg.addr = rt_cpu_to_le32(ept->info.src);
|
||||
ns_msg.flags = rt_cpu_to_le32(RT_RPMSG_NS_DESTROY);
|
||||
|
||||
err = rt_rpmsg_sendto(ept, RT_RPMSG_NS_ADDR, &ns_msg, sizeof(ns_msg));
|
||||
|
||||
if (err)
|
||||
{
|
||||
LOG_E("%s: Notify remote error = %s",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent), rt_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_rpmsg_send(struct rt_rpmsg_device *rdev,
|
||||
rt_uint32_t src, rt_uint32_t dst,
|
||||
const void *data, rt_size_t len, rt_int32_t timeout)
|
||||
{
|
||||
rt_base_t level;
|
||||
int idx;
|
||||
struct rt_virtqueue *vq;
|
||||
struct virtio_rpmsg_hdr *msg;
|
||||
struct virtio_rpmsg_tx_buf *tx_buf;
|
||||
struct virtio_rpmsg *vrpmsg = raw_to_virtio_rpmsg(rdev);
|
||||
|
||||
if (src == RT_RPMSG_ADDR_ANY || dst == RT_RPMSG_ADDR_ANY)
|
||||
{
|
||||
LOG_E("%s: Invalid addr(src: %u, dst: %u)",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent), src, dst);
|
||||
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
if (len > VIRTIO_RPMSG_MAX_BUF_SIZE - sizeof(*msg))
|
||||
{
|
||||
LOG_E("%s: Data's len = %u > %u is too big",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent),
|
||||
len, VIRTIO_RPMSG_MAX_BUF_SIZE - sizeof(*msg));
|
||||
|
||||
return -RT_EFULL;
|
||||
}
|
||||
|
||||
vq = vrpmsg->vqs[QUEUE_TX];
|
||||
rt_virtqueue_wait_prepare(vq, 1);
|
||||
|
||||
level = rt_spin_lock_irqsave(&vrpmsg->tx_lock);
|
||||
|
||||
idx = rt_virtqueue_next_buf_index(vq);
|
||||
tx_buf = (void *)vrpmsg->tx_buffer + idx * sizeof(struct virtio_rpmsg_tx_buf);
|
||||
tx_buf->idx = idx;
|
||||
msg = (void *)tx_buf->data;
|
||||
|
||||
msg->src = rt_cpu_to_le32(src);
|
||||
msg->dst = rt_cpu_to_le32(dst);
|
||||
msg->reserved = 0;
|
||||
msg->len = rt_cpu_to_le16(len);
|
||||
msg->flags = 0;
|
||||
LOG_D("%s: %cX-HDR(src: %u, dst: %u, len: %u, flags: %u, reserved: %u)",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent), 'T', src, dst, len, 0, 0);
|
||||
rt_memcpy(msg->data, data, len);
|
||||
|
||||
rt_virtqueue_add_outbuf(vq, msg, sizeof(*msg) + len);
|
||||
|
||||
rt_virtqueue_kick(vq);
|
||||
|
||||
rt_spin_unlock_irqrestore(&vrpmsg->tx_lock, level);
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
rt_completion_wait(&vrpmsg->tx_done[idx], timeout);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct rt_rpmsg_ops virtio_rpmsg_ops =
|
||||
{
|
||||
.create_endpoint = virtio_rpmsg_create_endpoint,
|
||||
.destroy_endpoint = virtio_rpmsg_destroy_endpoint,
|
||||
.send = virtio_rpmsg_send,
|
||||
};
|
||||
|
||||
static void virtio_rpmsg_rx_done(struct rt_virtqueue *vq)
|
||||
{
|
||||
rt_size_t len, msg_len;
|
||||
struct rt_rpmsg_device *rdev;
|
||||
struct rt_rpmsg_endpoint *ept;
|
||||
struct rt_rpmsg_endpoint_info info;
|
||||
struct virtio_rpmsg_hdr *msg;
|
||||
struct virtio_rpmsg *vrpmsg = vq->vdev->priv;
|
||||
|
||||
rdev = &vrpmsg->parent;
|
||||
msg = rt_virtqueue_read_buf(vq, &len);
|
||||
|
||||
if (!msg)
|
||||
{
|
||||
LOG_D("%s: not used buffer", rt_dm_dev_get_name(&vrpmsg->vdev->parent));
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
msg_len = rt_le16_to_cpu(msg->len);
|
||||
|
||||
LOG_D("%s: %cX-HDR(src: %u, dst: %u, len: %u, flags: %u, reserved: %u)",
|
||||
rt_dm_dev_get_name(&vrpmsg->vdev->parent), 'R',
|
||||
rt_le32_to_cpu(msg->src),
|
||||
rt_le32_to_cpu(msg->dst),
|
||||
msg_len,
|
||||
rt_le16_to_cpu(msg->flags),
|
||||
rt_le32_to_cpu(msg->reserved));
|
||||
|
||||
info.src = rt_le32_to_cpu(msg->dst);
|
||||
info.dst = RT_RPMSG_ADDR_ANY;
|
||||
info.name[0] = '\0';
|
||||
|
||||
if (rt_le32_to_cpu(msg->dst) == RT_RPMSG_NS_ADDR && vrpmsg->ns)
|
||||
{
|
||||
ept = rt_rpmsg_find_endpoint(vrpmsg->ns, &info);
|
||||
}
|
||||
else
|
||||
{
|
||||
ept = rt_rpmsg_find_endpoint(rdev, &info);
|
||||
}
|
||||
|
||||
if (ept && ept->rx_callback)
|
||||
{
|
||||
ept->rx_callback(rdev, rt_le32_to_cpu(msg->src), msg->data, msg_len);
|
||||
}
|
||||
|
||||
rt_virtqueue_add_inbuf(vq, msg, VIRTIO_RPMSG_MAX_BUF_SIZE);
|
||||
|
||||
rt_virtqueue_kick(vq);
|
||||
|
||||
msg = rt_virtqueue_read_buf(vq, &len);
|
||||
} while (msg);
|
||||
}
|
||||
|
||||
static void virtio_rpmsg_tx_done(struct rt_virtqueue *vq)
|
||||
{
|
||||
rt_ubase_t level;
|
||||
struct virtio_rpmsg_tx_buf *tx_buf;
|
||||
struct virtio_rpmsg *vrpmsg = vq->vdev->priv;
|
||||
|
||||
level = rt_spin_lock_irqsave(&vrpmsg->tx_lock);
|
||||
|
||||
while ((tx_buf = rt_virtqueue_read_buf(vq, RT_NULL)))
|
||||
{
|
||||
rt_completion_done(&vrpmsg->tx_done[tx_buf->idx]);
|
||||
}
|
||||
|
||||
rt_spin_unlock_irqrestore(&vrpmsg->tx_lock, level);
|
||||
}
|
||||
|
||||
static rt_err_t virtio_rpmsg_vq_init(struct virtio_rpmsg *vrpmsg)
|
||||
{
|
||||
rt_err_t err;
|
||||
rt_size_t vqs_nr = 2, qsize;
|
||||
void *rx_buffer;
|
||||
const char *names[RT_ARRAY_SIZE(vrpmsg->vqs)];
|
||||
rt_virtqueue_callback cbs[RT_ARRAY_SIZE(vrpmsg->vqs)];
|
||||
struct rt_virtio_device *vdev = vrpmsg->vdev;
|
||||
struct rt_virtqueue *vq;
|
||||
|
||||
names[QUEUE_RX] = "rx";
|
||||
names[QUEUE_TX] = "tx";
|
||||
|
||||
cbs[QUEUE_RX] = &virtio_rpmsg_rx_done;
|
||||
cbs[QUEUE_TX] = &virtio_rpmsg_tx_done;
|
||||
|
||||
err = rt_virtio_virtqueue_install(vdev, vqs_nr, vrpmsg->vqs, names, cbs);
|
||||
|
||||
if (err)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
qsize = rt_virtqueue_get_virtq_size(vrpmsg->vqs[QUEUE_TX]);
|
||||
if (!(vrpmsg->tx_done = rt_malloc(sizeof(vrpmsg->tx_done[0]) * qsize)))
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < qsize; ++idx)
|
||||
{
|
||||
rt_completion_init(&vrpmsg->tx_done[idx]);
|
||||
}
|
||||
|
||||
vrpmsg->tx_buffer = rt_malloc(qsize * sizeof(struct virtio_rpmsg_tx_buf) +
|
||||
rt_virtqueue_get_virtq_size(vrpmsg->vqs[QUEUE_RX]) * VIRTIO_RPMSG_MAX_BUF_SIZE);
|
||||
|
||||
if (!vrpmsg->tx_buffer)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
vq = vrpmsg->vqs[QUEUE_RX];
|
||||
rx_buffer = vrpmsg->tx_buffer + qsize * sizeof(struct virtio_rpmsg_tx_buf);
|
||||
|
||||
for (int idx = 0; idx < qsize; ++idx, rx_buffer += VIRTIO_RPMSG_MAX_BUF_SIZE)
|
||||
{
|
||||
rt_virtqueue_add_inbuf(vq, rx_buffer, VIRTIO_RPMSG_MAX_BUF_SIZE);
|
||||
|
||||
rt_virtqueue_submit(vq);
|
||||
}
|
||||
|
||||
rt_virtqueue_notify(vq);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void virtio_rpmsg_vq_finit(struct virtio_rpmsg *vrpmsg)
|
||||
{
|
||||
if (vrpmsg->vqs[0])
|
||||
{
|
||||
rt_virtio_virtqueue_release(vrpmsg->vdev);
|
||||
}
|
||||
if (vrpmsg->tx_done)
|
||||
{
|
||||
rt_free(vrpmsg->tx_done);
|
||||
}
|
||||
if (vrpmsg->tx_buffer)
|
||||
{
|
||||
rt_free(vrpmsg->tx_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static rt_err_t virtio_rpmsg_probe(struct rt_virtio_device *vdev)
|
||||
{
|
||||
rt_err_t err = RT_EOK;
|
||||
struct virtio_rpmsg *vrpmsg;
|
||||
|
||||
if (rt_rpmsg_mode() == RT_RPMSG_MODE_SLAVE)
|
||||
{
|
||||
_queue_rx = 0;
|
||||
_queue_tx = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_queue_tx = 0;
|
||||
_queue_rx = 1;
|
||||
}
|
||||
|
||||
vrpmsg = rt_calloc(1, sizeof(*vrpmsg));
|
||||
|
||||
if (!vrpmsg)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
vdev->priv = vrpmsg;
|
||||
vrpmsg->vdev = vdev;
|
||||
vdev->parent.user_data = vrpmsg;
|
||||
|
||||
if ((err = virtio_rpmsg_vq_init(vrpmsg)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
rt_spin_lock_init(&vrpmsg->tx_lock);
|
||||
|
||||
rt_strncpy(vrpmsg->parent.id.name, "rpmsg-char", sizeof(vrpmsg->parent.id.name));
|
||||
vrpmsg->parent.ops = &virtio_rpmsg_ops;
|
||||
vrpmsg->parent.priv = vrpmsg;
|
||||
|
||||
if ((err = rt_rpmsg_device_register(&vrpmsg->parent)))
|
||||
{
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
/* Enable the name service */
|
||||
if ((vrpmsg->supp_ns = rt_virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)))
|
||||
{
|
||||
vrpmsg->ns = rt_calloc(1, sizeof(*vrpmsg->ns));
|
||||
|
||||
if (!vrpmsg->ns)
|
||||
{
|
||||
goto _fail_ns;
|
||||
}
|
||||
|
||||
rt_strncpy(vrpmsg->ns->id.name, "rpmsg-name-service", RT_RPMSG_NAME_SIZE);
|
||||
vrpmsg->ns->ops = &virtio_rpmsg_ops;
|
||||
vrpmsg->ns->priv = vrpmsg;
|
||||
|
||||
if ((err = rt_rpmsg_device_register(vrpmsg->ns)))
|
||||
{
|
||||
goto _fail_ns;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
|
||||
_fail_ns:
|
||||
rt_bus_remove_device(&vrpmsg->parent.parent);
|
||||
|
||||
_fail:
|
||||
virtio_rpmsg_vq_finit(vrpmsg);
|
||||
rt_free(vrpmsg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_rpmsg_remove(struct rt_virtio_device *vdev)
|
||||
{
|
||||
struct virtio_rpmsg *vrpmsg = vdev->parent.user_data;
|
||||
|
||||
rt_bus_remove_device(&vrpmsg->parent.parent);
|
||||
|
||||
if (vrpmsg->ns)
|
||||
{
|
||||
rt_bus_remove_device(&vrpmsg->ns->parent);
|
||||
}
|
||||
|
||||
virtio_rpmsg_vq_finit(vrpmsg);
|
||||
rt_free(vrpmsg);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct rt_virtio_device_id virtio_rpmsg_ids[] =
|
||||
{
|
||||
{ VIRTIO_DEVICE_ID_RPMSG, VIRTIO_DEVICE_ANY_ID },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct rt_virtio_driver virtio_rpmsg_driver =
|
||||
{
|
||||
.ids = virtio_rpmsg_ids,
|
||||
.features =
|
||||
RT_BIT(VIRTIO_RPMSG_F_NS)
|
||||
| RT_BIT(VIRTIO_F_ANY_LAYOUT),
|
||||
|
||||
.probe = virtio_rpmsg_probe,
|
||||
.remove = virtio_rpmsg_remove,
|
||||
};
|
||||
RT_VIRTIO_DRIVER_EXPORT(virtio_rpmsg_driver);
|
||||
Executable
+1847
File diff suppressed because it is too large
Load Diff
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __VIRTIO_RPMSG_H__
|
||||
#define __VIRTIO_RPMSG_H__
|
||||
|
||||
#include <drivers/core/dm.h>
|
||||
|
||||
#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */
|
||||
|
||||
#define VIRTIO_RPMSG_MAX_BUF_SIZE 512
|
||||
#define VIRTIO_RPMSG_RESERVED_ADDRESSES 1024
|
||||
|
||||
rt_packed(struct virtio_rpmsg_hdr
|
||||
{
|
||||
rt_le32_t src;
|
||||
rt_le32_t dst;
|
||||
rt_le32_t reserved;
|
||||
rt_le16_t len;
|
||||
rt_le16_t flags;
|
||||
rt_uint8_t data[];
|
||||
});
|
||||
|
||||
#endif /* __VIRTIO_RPMSG_H__ */
|
||||
+441
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef __VIRTIO_SOUND_H__
|
||||
#define __VIRTIO_SOUND_H__
|
||||
|
||||
#include <drivers/core/dm.h>
|
||||
|
||||
#define VIRTIO_SOUND_F_CTLS 1
|
||||
|
||||
struct virtio_snd_config
|
||||
{
|
||||
/* available physical jacks */
|
||||
rt_le32_t jacks;
|
||||
/* available PCM streams */
|
||||
rt_le32_t streams;
|
||||
/* available channel maps */
|
||||
rt_le32_t chmaps;
|
||||
/* available control elements if VIRTIO_SND_F_CTLS has been negotiated */
|
||||
rt_le32_t controls;
|
||||
};
|
||||
|
||||
/* supported dataflow directions */
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_D_OUTPUT = 0,
|
||||
VIRTIO_SND_D_INPUT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* jack control request types */
|
||||
VIRTIO_SND_R_JACK_INFO = 1,
|
||||
VIRTIO_SND_R_JACK_REMAP,
|
||||
|
||||
/* PCM control request types */
|
||||
VIRTIO_SND_R_PCM_INFO = 0x0100,
|
||||
VIRTIO_SND_R_PCM_SET_PARAMS,
|
||||
VIRTIO_SND_R_PCM_PREPARE,
|
||||
VIRTIO_SND_R_PCM_RELEASE,
|
||||
VIRTIO_SND_R_PCM_START,
|
||||
VIRTIO_SND_R_PCM_STOP,
|
||||
|
||||
/* channel map control request types */
|
||||
VIRTIO_SND_R_CHMAP_INFO = 0x0200,
|
||||
|
||||
/* jack event types */
|
||||
VIRTIO_SND_EVT_JACK_CONNECTED = 0x1000,
|
||||
VIRTIO_SND_EVT_JACK_DISCONNECTED,
|
||||
|
||||
/* PCM event types */
|
||||
VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED = 0x1100,
|
||||
VIRTIO_SND_EVT_PCM_XRUN,
|
||||
|
||||
/* common status codes */
|
||||
VIRTIO_SND_S_OK = 0x8000,
|
||||
VIRTIO_SND_S_BAD_MSG,
|
||||
VIRTIO_SND_S_NOT_SUPP,
|
||||
VIRTIO_SND_S_IO_ERR
|
||||
};
|
||||
|
||||
/* common header */
|
||||
struct virtio_snd_hdr
|
||||
{
|
||||
rt_le32_t code;
|
||||
};
|
||||
|
||||
/* event notification */
|
||||
struct virtio_snd_event
|
||||
{
|
||||
/* VIRTIO_SND_EVT_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* optional event data */
|
||||
rt_le32_t data;
|
||||
};
|
||||
|
||||
/* common control request to query an item information */
|
||||
struct virtio_snd_query_info
|
||||
{
|
||||
/* VIRTIO_SND_R_XXX_INFO */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* item start identifier */
|
||||
rt_le32_t start_id;
|
||||
/* item count to query */
|
||||
rt_le32_t count;
|
||||
/* item information size in bytes */
|
||||
rt_le32_t size;
|
||||
};
|
||||
|
||||
/* common item information header */
|
||||
struct virtio_snd_info
|
||||
{
|
||||
/* function group node id (High Definition Audio Specification 7.1.2) */
|
||||
rt_le32_t hda_fn_nid;
|
||||
};
|
||||
|
||||
struct virtio_snd_jack_hdr
|
||||
{
|
||||
/* VIRTIO_SND_R_JACK_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* 0 ... virtio_snd_config::jacks - 1 */
|
||||
rt_le32_t jack_id;
|
||||
};
|
||||
|
||||
/* supported jack features */
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_JACK_F_REMAP = 0
|
||||
};
|
||||
|
||||
struct virtio_snd_jack_info
|
||||
{
|
||||
/* common header */
|
||||
struct virtio_snd_info hdr;
|
||||
/* supported feature bit map (1 << VIRTIO_SND_JACK_F_XXX) */
|
||||
rt_le32_t features;
|
||||
/* pin configuration (High Definition Audio Specification 7.3.3.31) */
|
||||
rt_le32_t hda_reg_defconf;
|
||||
/* pin capabilities (High Definition Audio Specification 7.3.4.9) */
|
||||
rt_le32_t hda_reg_caps;
|
||||
/* current jack connection status (0: disconnected, 1: connected) */
|
||||
rt_uint8_t connected;
|
||||
|
||||
rt_uint8_t padding[7];
|
||||
};
|
||||
|
||||
/* jack remapping control request */
|
||||
struct virtio_snd_jack_remap
|
||||
{
|
||||
/* .code = VIRTIO_SND_R_JACK_REMAP */
|
||||
struct virtio_snd_jack_hdr hdr;
|
||||
/* selected association number */
|
||||
rt_le32_t association;
|
||||
/* selected sequence number */
|
||||
rt_le32_t sequence;
|
||||
};
|
||||
|
||||
struct virtio_snd_pcm_hdr
|
||||
{
|
||||
/* VIRTIO_SND_R_PCM_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* 0 ... virtio_snd_config::streams - 1 */
|
||||
rt_le32_t stream_id;
|
||||
};
|
||||
|
||||
/* supported PCM stream features */
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_PCM_F_SHMEM_HOST = 0,
|
||||
VIRTIO_SND_PCM_F_SHMEM_GUEST,
|
||||
VIRTIO_SND_PCM_F_MSG_POLLING,
|
||||
VIRTIO_SND_PCM_F_EVT_SHMEM_PERIODS,
|
||||
VIRTIO_SND_PCM_F_EVT_XRUNS
|
||||
};
|
||||
|
||||
/* supported PCM sample formats */
|
||||
enum
|
||||
{
|
||||
/* analog formats (width / physical width) */
|
||||
VIRTIO_SND_PCM_FMT_IMA_ADPCM = 0, /* 4 / 4 bits */
|
||||
VIRTIO_SND_PCM_FMT_MU_LAW, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_A_LAW, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_S8, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_U8, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_S16, /* 16 / 16 bits */
|
||||
VIRTIO_SND_PCM_FMT_U16, /* 16 / 16 bits */
|
||||
VIRTIO_SND_PCM_FMT_S18_3, /* 18 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_U18_3, /* 18 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_S20_3, /* 20 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_U20_3, /* 20 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_S24_3, /* 24 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_U24_3, /* 24 / 24 bits */
|
||||
VIRTIO_SND_PCM_FMT_S20, /* 20 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_U20, /* 20 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_S24, /* 24 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_U24, /* 24 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_S32, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_U32, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_FLOAT, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_FLOAT64, /* 64 / 64 bits */
|
||||
/* digital formats (width / physical width) */
|
||||
VIRTIO_SND_PCM_FMT_DSD_U8, /* 8 / 8 bits */
|
||||
VIRTIO_SND_PCM_FMT_DSD_U16, /* 16 / 16 bits */
|
||||
VIRTIO_SND_PCM_FMT_DSD_U32, /* 32 / 32 bits */
|
||||
VIRTIO_SND_PCM_FMT_IEC958_SUBFRAME /* 32 / 32 bits */
|
||||
};
|
||||
|
||||
/* supported PCM frame rates */
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_PCM_RATE_5512 = 0,
|
||||
VIRTIO_SND_PCM_RATE_8000,
|
||||
VIRTIO_SND_PCM_RATE_11025,
|
||||
VIRTIO_SND_PCM_RATE_16000,
|
||||
VIRTIO_SND_PCM_RATE_22050,
|
||||
VIRTIO_SND_PCM_RATE_32000,
|
||||
VIRTIO_SND_PCM_RATE_44100,
|
||||
VIRTIO_SND_PCM_RATE_48000,
|
||||
VIRTIO_SND_PCM_RATE_64000,
|
||||
VIRTIO_SND_PCM_RATE_88200,
|
||||
VIRTIO_SND_PCM_RATE_96000,
|
||||
VIRTIO_SND_PCM_RATE_176400,
|
||||
VIRTIO_SND_PCM_RATE_192000,
|
||||
VIRTIO_SND_PCM_RATE_384000
|
||||
};
|
||||
|
||||
struct virtio_snd_pcm_info
|
||||
{
|
||||
/* common header */
|
||||
struct virtio_snd_info hdr;
|
||||
/* supported feature bit map (1 << VIRTIO_SND_PCM_F_XXX) */
|
||||
rt_le32_t features;
|
||||
/* supported sample format bit map (1 << VIRTIO_SND_PCM_FMT_XXX) */
|
||||
rt_le64_t formats;
|
||||
/* supported frame rate bit map (1 << VIRTIO_SND_PCM_RATE_XXX) */
|
||||
rt_le64_t rates;
|
||||
/* dataflow direction (VIRTIO_SND_D_XXX) */
|
||||
rt_uint8_t direction;
|
||||
/* minimum # of supported channels */
|
||||
rt_uint8_t channels_min;
|
||||
/* maximum # of supported channels */
|
||||
rt_uint8_t channels_max;
|
||||
|
||||
rt_uint8_t padding[5];
|
||||
};
|
||||
|
||||
/* set PCM stream format */
|
||||
struct virtio_snd_pcm_set_params
|
||||
{
|
||||
/* .code = VIRTIO_SND_R_PCM_SET_PARAMS */
|
||||
struct virtio_snd_pcm_hdr hdr;
|
||||
/* size of the hardware buffer */
|
||||
rt_le32_t buffer_bytes;
|
||||
/* size of the hardware period */
|
||||
rt_le32_t period_bytes;
|
||||
/* selected feature bit map (1 << VIRTIO_SND_PCM_F_XXX) */
|
||||
rt_le32_t features;
|
||||
/* selected # of channels */
|
||||
rt_uint8_t channels;
|
||||
/* selected sample format (VIRTIO_SND_PCM_FMT_XXX) */
|
||||
rt_uint8_t format;
|
||||
/* selected frame rate (VIRTIO_SND_PCM_RATE_XXX) */
|
||||
rt_uint8_t rate;
|
||||
|
||||
rt_uint8_t padding;
|
||||
};
|
||||
|
||||
/* I/O request header */
|
||||
struct virtio_snd_pcm_xfer
|
||||
{
|
||||
/* 0 ... virtio_snd_config::streams - 1 */
|
||||
rt_le32_t stream_id;
|
||||
};
|
||||
|
||||
/* I/O request status */
|
||||
struct virtio_snd_pcm_status
|
||||
{
|
||||
/* VIRTIO_SND_S_XXX */
|
||||
rt_le32_t status;
|
||||
/* current device latency */
|
||||
rt_le32_t latency_bytes;
|
||||
};
|
||||
|
||||
struct virtio_snd_chmap_hdr
|
||||
{
|
||||
/* VIRTIO_SND_R_CHMAP_XXX */
|
||||
struct virtio_snd_hdr hdr;
|
||||
/* 0 ... virtio_snd_config::chmaps - 1 */
|
||||
rt_le32_t chmap_id;
|
||||
};
|
||||
|
||||
/* standard channel position definition */
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_CHMAP_NONE = 0, /* undefined */
|
||||
VIRTIO_SND_CHMAP_NA, /* silent */
|
||||
VIRTIO_SND_CHMAP_MONO, /* mono stream */
|
||||
VIRTIO_SND_CHMAP_FL, /* front left */
|
||||
VIRTIO_SND_CHMAP_FR, /* front right */
|
||||
VIRTIO_SND_CHMAP_RL, /* rear left */
|
||||
VIRTIO_SND_CHMAP_RR, /* rear right */
|
||||
VIRTIO_SND_CHMAP_FC, /* front center */
|
||||
VIRTIO_SND_CHMAP_LFE, /* low frequency (LFE) */
|
||||
VIRTIO_SND_CHMAP_SL, /* side left */
|
||||
VIRTIO_SND_CHMAP_SR, /* side right */
|
||||
VIRTIO_SND_CHMAP_RC, /* rear center */
|
||||
VIRTIO_SND_CHMAP_FLC, /* front left center */
|
||||
VIRTIO_SND_CHMAP_FRC, /* front right center */
|
||||
VIRTIO_SND_CHMAP_RLC, /* rear left center */
|
||||
VIRTIO_SND_CHMAP_RRC, /* rear right center */
|
||||
VIRTIO_SND_CHMAP_FLW, /* front left wide */
|
||||
VIRTIO_SND_CHMAP_FRW, /* front right wide */
|
||||
VIRTIO_SND_CHMAP_FLH, /* front left high */
|
||||
VIRTIO_SND_CHMAP_FCH, /* front center high */
|
||||
VIRTIO_SND_CHMAP_FRH, /* front right high */
|
||||
VIRTIO_SND_CHMAP_TC, /* top center */
|
||||
VIRTIO_SND_CHMAP_TFL, /* top front left */
|
||||
VIRTIO_SND_CHMAP_TFR, /* top front right */
|
||||
VIRTIO_SND_CHMAP_TFC, /* top front center */
|
||||
VIRTIO_SND_CHMAP_TRL, /* top rear left */
|
||||
VIRTIO_SND_CHMAP_TRR, /* top rear right */
|
||||
VIRTIO_SND_CHMAP_TRC, /* top rear center */
|
||||
VIRTIO_SND_CHMAP_TFLC, /* top front left center */
|
||||
VIRTIO_SND_CHMAP_TFRC, /* top front right center */
|
||||
VIRTIO_SND_CHMAP_TSL, /* top side left */
|
||||
VIRTIO_SND_CHMAP_TSR, /* top side right */
|
||||
VIRTIO_SND_CHMAP_LLFE, /* left LFE */
|
||||
VIRTIO_SND_CHMAP_RLFE, /* right LFE */
|
||||
VIRTIO_SND_CHMAP_BC, /* bottom center */
|
||||
VIRTIO_SND_CHMAP_BLC, /* bottom left center */
|
||||
VIRTIO_SND_CHMAP_BRC /* bottom right center */
|
||||
};
|
||||
|
||||
/* maximum possible number of channels */
|
||||
#define VIRTIO_SND_CHMAP_MAX_SIZE 18
|
||||
|
||||
struct virtio_snd_chmap_info
|
||||
{
|
||||
/* common header */
|
||||
struct virtio_snd_info hdr;
|
||||
/* dataflow direction (VIRTIO_SND_D_XXX) */
|
||||
rt_uint8_t direction;
|
||||
/* # of valid channel position values */
|
||||
rt_uint8_t channels;
|
||||
/* channel position values (VIRTIO_SND_CHMAP_XXX) */
|
||||
rt_uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_CTL_ROLE_UNDEFINED = 0,
|
||||
VIRTIO_SND_CTL_ROLE_VOLUME,
|
||||
VIRTIO_SND_CTL_ROLE_MUTE,
|
||||
VIRTIO_SND_CTL_ROLE_GAIN
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_CTL_TYPE_BOOLEAN = 0,
|
||||
VIRTIO_SND_CTL_TYPE_INTEGER,
|
||||
VIRTIO_SND_CTL_TYPE_INTEGER64,
|
||||
VIRTIO_SND_CTL_TYPE_ENUMERATED,
|
||||
VIRTIO_SND_CTL_TYPE_BYTES,
|
||||
VIRTIO_SND_CTL_TYPE_IEC958
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_CTL_ACCESS_READ = 0,
|
||||
VIRTIO_SND_CTL_ACCESS_WRITE,
|
||||
VIRTIO_SND_CTL_ACCESS_VOLATILE,
|
||||
VIRTIO_SND_CTL_ACCESS_INACTIVE,
|
||||
VIRTIO_SND_CTL_ACCESS_TLV_READ,
|
||||
VIRTIO_SND_CTL_ACCESS_TLV_WRITE,
|
||||
VIRTIO_SND_CTL_ACCESS_TLV_COMMAND
|
||||
};
|
||||
|
||||
struct virtio_snd_ctl_info
|
||||
{
|
||||
struct virtio_snd_info hdr;
|
||||
rt_le32_t role;
|
||||
rt_le32_t type;
|
||||
rt_le32_t access; /* 1 << VIRTIO_SND_CTL_ACCESS_XXX */
|
||||
rt_le32_t count;
|
||||
rt_le32_t index;
|
||||
rt_uint8_t name[44];
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
rt_le32_t min;
|
||||
rt_le32_t max;
|
||||
rt_le32_t step;
|
||||
} integer;
|
||||
struct
|
||||
{
|
||||
rt_le64_t min;
|
||||
rt_le64_t max;
|
||||
rt_le64_t step;
|
||||
} integer64;
|
||||
struct
|
||||
{
|
||||
rt_le32_t items;
|
||||
} enumerated;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct virtio_snd_ctl_enum_item
|
||||
{
|
||||
rt_uint8_t item[64];
|
||||
};
|
||||
|
||||
struct virtio_snd_ctl_iec958
|
||||
{
|
||||
rt_uint8_t status[24]; /* AES/IEC958 channel status bits */
|
||||
rt_uint8_t subcode[147]; /* AES/IEC958 subcode bits */
|
||||
rt_uint8_t pad; /* nothing */
|
||||
rt_uint8_t dig_subframe[4]; /* AES/IEC958 subframe bits */
|
||||
};
|
||||
|
||||
struct virtio_snd_ctl_value
|
||||
{
|
||||
union
|
||||
{
|
||||
rt_le32_t integer[128];
|
||||
rt_le64_t integer64[64];
|
||||
rt_le32_t enumerated[128];
|
||||
rt_uint8_t bytes[512];
|
||||
struct virtio_snd_ctl_iec958 iec958;
|
||||
} value;
|
||||
};
|
||||
|
||||
struct virtio_snd_ctl_tlv
|
||||
{
|
||||
rt_le32_t type;
|
||||
rt_le32_t length;
|
||||
rt_le32_t value[];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
VIRTIO_SND_CTL_EVT_MASK_VALUE = 0,
|
||||
VIRTIO_SND_CTL_EVT_MASK_INFO,
|
||||
VIRTIO_SND_CTL_EVT_MASK_TLV
|
||||
};
|
||||
|
||||
struct virtio_snd_ctl_event
|
||||
{
|
||||
struct virtio_snd_hdr hdr; /* .code = VIRTIO_SND_EVT_CTL_NOTIFY */
|
||||
rt_le16_t control_id;
|
||||
rt_le16_t mask; /* 1 << VIRTIO_SND_CTL_EVT_MASK_XXX */
|
||||
};
|
||||
|
||||
#endif /* __VIRTIO_SOUND_H__ */
|
||||
Reference in New Issue
Block a user