use crate::{ device::queue::{ direction::{Capture, Direction, Output}, qbuf::{ CaptureQueueable, CaptureQueueableProvider, OutputQueueable, OutputQueueableProvider, QBuffer, QueueResult, }, BuffersAllocated, Queue, }, memory::DmaBufHandle, }; use crate::{ memory::MmapHandle, memory::{BufferHandles, MemoryType, UserPtrHandle}, }; use std::{fmt::Debug, fs::File}; /// 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 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), User(Vec>>), DmaBuf(Vec>), } impl From> for GenericBufferHandles { fn from(m: Vec) -> Self { Self::Mmap(m) } } impl From>>> for GenericBufferHandles { fn from(u: Vec>>) -> Self { Self::User(u) } } impl From>> for GenericBufferHandles { fn from(d: Vec>) -> 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<'a, D: Direction> { Mmap(QBuffer<'a, D, Vec, GenericBufferHandles>), User(QBuffer<'a, D, Vec>>, GenericBufferHandles>), DmaBuf(QBuffer<'a, D, Vec>, GenericBufferHandles>), } impl<'a, D: Direction> From, GenericBufferHandles>> for GenericQBuffer<'a, D> { fn from(qb: QBuffer<'a, D, Vec, GenericBufferHandles>) -> Self { GenericQBuffer::Mmap(qb) } } impl<'a, D: Direction> From>>, GenericBufferHandles>> for GenericQBuffer<'a, D> { fn from(qb: QBuffer<'a, D, Vec>>, GenericBufferHandles>) -> Self { GenericQBuffer::User(qb) } } impl<'a, D: Direction> From>, GenericBufferHandles>> for GenericQBuffer<'a, D> { fn from(qb: QBuffer<'a, D, Vec>, GenericBufferHandles>) -> Self { GenericQBuffer::DmaBuf(qb) } } /// Any CAPTURE GenericQBuffer implements CaptureQueueable. impl CaptureQueueable for GenericQBuffer<'_, Capture> { 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 OutputQueueable for GenericQBuffer<'_, Output> { 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), } } } impl<'a> CaptureQueueableProvider<'a, GenericBufferHandles> for Queue> { type Queueable = GenericQBuffer<'a, Capture>; } impl<'a> OutputQueueableProvider<'a, GenericBufferHandles> for Queue> { type Queueable = GenericQBuffer<'a, Output>; }