blob: a590fc944bd4276fe295a202025172f2d87af363 [file] [log] [blame]
use crate::{
device::queue::{
direction::{Capture, Direction, Output},
private,
qbuf::{QBuffer, QueueResult},
BuffersAllocated, CaptureQueueable, OutputQueueable, Queue, TryGetBufferError,
},
memory::DmaBufHandle,
};
use crate::{
memory::MmapHandle,
memory::{BufferHandles, MemoryType, UserPtrHandle},
};
use std::{fmt::Debug, fs::File, ops::Deref};
/// Supported memory types for `GenericBufferHandles`.
/// TODO: This should be renamed to "DynamicBufferHandles", and be constructed
/// on-the-fly using a macro.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GenericSupportedMemoryType {
Mmap,
UserPtr,
DmaBuf,
}
impl From<GenericSupportedMemoryType> for MemoryType {
fn from(mem_type: GenericSupportedMemoryType) -> Self {
match mem_type {
GenericSupportedMemoryType::Mmap => MemoryType::Mmap,
GenericSupportedMemoryType::UserPtr => MemoryType::UserPtr,
GenericSupportedMemoryType::DmaBuf => MemoryType::DmaBuf,
}
}
}
/// Buffer handle capable of holding either MMAP or UserPtr handles. Useful
/// for cases when we want to decide the memory type of a queue at runtime.
#[derive(Debug)]
pub enum GenericBufferHandles {
Mmap(Vec<MmapHandle>),
User(Vec<UserPtrHandle<Vec<u8>>>),
DmaBuf(Vec<DmaBufHandle<File>>),
}
impl From<Vec<MmapHandle>> for GenericBufferHandles {
fn from(m: Vec<MmapHandle>) -> Self {
Self::Mmap(m)
}
}
impl From<Vec<UserPtrHandle<Vec<u8>>>> for GenericBufferHandles {
fn from(u: Vec<UserPtrHandle<Vec<u8>>>) -> Self {
Self::User(u)
}
}
impl From<Vec<DmaBufHandle<File>>> for GenericBufferHandles {
fn from(d: Vec<DmaBufHandle<File>>) -> Self {
Self::DmaBuf(d)
}
}
impl BufferHandles for GenericBufferHandles {
type SupportedMemoryType = GenericSupportedMemoryType;
fn len(&self) -> usize {
match self {
GenericBufferHandles::Mmap(m) => m.len(),
GenericBufferHandles::User(u) => u.len(),
GenericBufferHandles::DmaBuf(d) => d.len(),
}
}
fn fill_v4l2_plane(&self, index: usize, plane: &mut crate::bindings::v4l2_plane) {
match self {
GenericBufferHandles::Mmap(m) => m.fill_v4l2_plane(index, plane),
GenericBufferHandles::User(u) => u.fill_v4l2_plane(index, plane),
GenericBufferHandles::DmaBuf(d) => d.fill_v4l2_plane(index, plane),
}
}
}
/// A QBuffer that holds either MMAP or UserPtr handles, depending on which
/// memory type has been selected for the queue at runtime.
pub enum GenericQBuffer<
D: Direction,
Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>,
> {
Mmap(QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>),
User(QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>),
DmaBuf(QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>),
}
impl<D, Q> From<QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>> for GenericQBuffer<D, Q>
where
D: Direction,
Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>,
{
fn from(qb: QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>) -> Self {
GenericQBuffer::Mmap(qb)
}
}
impl<D, Q> From<QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>>
for GenericQBuffer<D, Q>
where
D: Direction,
Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>,
{
fn from(qb: QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>) -> Self {
GenericQBuffer::User(qb)
}
}
impl<D, Q> From<QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>>
for GenericQBuffer<D, Q>
where
D: Direction,
Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>,
{
fn from(qb: QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>) -> Self {
GenericQBuffer::DmaBuf(qb)
}
}
impl<'a, D: Direction> private::QueueableProvider<'a>
for Queue<D, BuffersAllocated<GenericBufferHandles>>
{
type Queueable = GenericQBuffer<D, &'a Self>;
}
impl<'a, D: Direction> private::GetBufferByIndex<'a>
for Queue<D, BuffersAllocated<GenericBufferHandles>>
{
fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> {
let buffer_info = self.try_obtain_buffer(index)?;
Ok(match self.state.memory_type {
GenericSupportedMemoryType::Mmap => {
GenericQBuffer::Mmap(QBuffer::new(self, buffer_info))
}
GenericSupportedMemoryType::UserPtr => {
GenericQBuffer::User(QBuffer::new(self, buffer_info))
}
GenericSupportedMemoryType::DmaBuf => {
GenericQBuffer::DmaBuf(QBuffer::new(self, buffer_info))
}
})
}
}
/// Any CAPTURE GenericQBuffer implements CaptureQueueable.
impl<Q> CaptureQueueable<GenericBufferHandles> for GenericQBuffer<Capture, Q>
where
Q: Deref<Target = Queue<Capture, BuffersAllocated<GenericBufferHandles>>>,
{
fn queue_with_handles(
self,
handles: GenericBufferHandles,
) -> QueueResult<(), GenericBufferHandles> {
match self {
GenericQBuffer::Mmap(m) => m.queue_with_handles(handles),
GenericQBuffer::User(u) => u.queue_with_handles(handles),
GenericQBuffer::DmaBuf(d) => d.queue_with_handles(handles),
}
}
}
/// Any OUTPUT GenericQBuffer implements OutputQueueable.
impl<Q> OutputQueueable<GenericBufferHandles> for GenericQBuffer<Output, Q>
where
Q: Deref<Target = Queue<Output, BuffersAllocated<GenericBufferHandles>>>,
{
fn queue_with_handles(
self,
handles: GenericBufferHandles,
bytes_used: &[usize],
) -> QueueResult<(), GenericBufferHandles> {
match self {
GenericQBuffer::Mmap(m) => m.queue_with_handles(handles, bytes_used),
GenericQBuffer::User(u) => u.queue_with_handles(handles, bytes_used),
GenericQBuffer::DmaBuf(d) => d.queue_with_handles(handles, bytes_used),
}
}
}