1 use crate::{ 2 device::queue::{ 3 direction::{Capture, Direction, Output}, 4 private, 5 qbuf::{QBuffer, QueueResult}, 6 BuffersAllocated, CaptureQueueable, OutputQueueable, Queue, TryGetBufferError, 7 }, 8 memory::DmaBufHandle, 9 }; 10 use crate::{ 11 memory::MmapHandle, 12 memory::{BufferHandles, MemoryType, UserPtrHandle}, 13 }; 14 use std::{fmt::Debug, fs::File, ops::Deref}; 15 16 /// Supported memory types for `GenericBufferHandles`. 17 /// TODO: This should be renamed to "DynamicBufferHandles", and be constructed 18 /// on-the-fly using a macro. 19 #[derive(Debug, Clone, Copy, PartialEq)] 20 pub enum GenericSupportedMemoryType { 21 Mmap, 22 UserPtr, 23 DmaBuf, 24 } 25 26 impl From<GenericSupportedMemoryType> for MemoryType { from(mem_type: GenericSupportedMemoryType) -> Self27 fn from(mem_type: GenericSupportedMemoryType) -> Self { 28 match mem_type { 29 GenericSupportedMemoryType::Mmap => MemoryType::Mmap, 30 GenericSupportedMemoryType::UserPtr => MemoryType::UserPtr, 31 GenericSupportedMemoryType::DmaBuf => MemoryType::DmaBuf, 32 } 33 } 34 } 35 36 /// Buffer handle capable of holding either MMAP or UserPtr handles. Useful 37 /// for cases when we want to decide the memory type of a queue at runtime. 38 #[derive(Debug)] 39 pub enum GenericBufferHandles { 40 Mmap(Vec<MmapHandle>), 41 User(Vec<UserPtrHandle<Vec<u8>>>), 42 DmaBuf(Vec<DmaBufHandle<File>>), 43 } 44 45 impl From<Vec<MmapHandle>> for GenericBufferHandles { from(m: Vec<MmapHandle>) -> Self46 fn from(m: Vec<MmapHandle>) -> Self { 47 Self::Mmap(m) 48 } 49 } 50 51 impl From<Vec<UserPtrHandle<Vec<u8>>>> for GenericBufferHandles { from(u: Vec<UserPtrHandle<Vec<u8>>>) -> Self52 fn from(u: Vec<UserPtrHandle<Vec<u8>>>) -> Self { 53 Self::User(u) 54 } 55 } 56 57 impl From<Vec<DmaBufHandle<File>>> for GenericBufferHandles { from(d: Vec<DmaBufHandle<File>>) -> Self58 fn from(d: Vec<DmaBufHandle<File>>) -> Self { 59 Self::DmaBuf(d) 60 } 61 } 62 63 impl BufferHandles for GenericBufferHandles { 64 type SupportedMemoryType = GenericSupportedMemoryType; 65 len(&self) -> usize66 fn len(&self) -> usize { 67 match self { 68 GenericBufferHandles::Mmap(m) => m.len(), 69 GenericBufferHandles::User(u) => u.len(), 70 GenericBufferHandles::DmaBuf(d) => d.len(), 71 } 72 } 73 fill_v4l2_plane(&self, index: usize, plane: &mut crate::bindings::v4l2_plane)74 fn fill_v4l2_plane(&self, index: usize, plane: &mut crate::bindings::v4l2_plane) { 75 match self { 76 GenericBufferHandles::Mmap(m) => m.fill_v4l2_plane(index, plane), 77 GenericBufferHandles::User(u) => u.fill_v4l2_plane(index, plane), 78 GenericBufferHandles::DmaBuf(d) => d.fill_v4l2_plane(index, plane), 79 } 80 } 81 } 82 83 /// A QBuffer that holds either MMAP or UserPtr handles, depending on which 84 /// memory type has been selected for the queue at runtime. 85 pub enum GenericQBuffer< 86 D: Direction, 87 Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, 88 > { 89 Mmap(QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>), 90 User(QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>), 91 DmaBuf(QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>), 92 } 93 94 impl<D, Q> From<QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>> for GenericQBuffer<D, Q> 95 where 96 D: Direction, 97 Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, 98 { from(qb: QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>) -> Self99 fn from(qb: QBuffer<D, Vec<MmapHandle>, GenericBufferHandles, Q>) -> Self { 100 GenericQBuffer::Mmap(qb) 101 } 102 } 103 104 impl<D, Q> From<QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>> 105 for GenericQBuffer<D, Q> 106 where 107 D: Direction, 108 Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, 109 { from(qb: QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>) -> Self110 fn from(qb: QBuffer<D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles, Q>) -> Self { 111 GenericQBuffer::User(qb) 112 } 113 } 114 115 impl<D, Q> From<QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>> 116 for GenericQBuffer<D, Q> 117 where 118 D: Direction, 119 Q: Deref<Target = Queue<D, BuffersAllocated<GenericBufferHandles>>>, 120 { from(qb: QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>) -> Self121 fn from(qb: QBuffer<D, Vec<DmaBufHandle<File>>, GenericBufferHandles, Q>) -> Self { 122 GenericQBuffer::DmaBuf(qb) 123 } 124 } 125 126 impl<'a, D: Direction> private::QueueableProvider<'a> 127 for Queue<D, BuffersAllocated<GenericBufferHandles>> 128 { 129 type Queueable = GenericQBuffer<D, &'a Self>; 130 } 131 132 impl<'a, D: Direction> private::GetBufferByIndex<'a> 133 for Queue<D, BuffersAllocated<GenericBufferHandles>> 134 { try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError>135 fn try_get_buffer(&'a self, index: usize) -> Result<Self::Queueable, TryGetBufferError> { 136 let buffer_info = self.try_obtain_buffer(index)?; 137 138 Ok(match self.state.memory_type { 139 GenericSupportedMemoryType::Mmap => { 140 GenericQBuffer::Mmap(QBuffer::new(self, buffer_info)) 141 } 142 GenericSupportedMemoryType::UserPtr => { 143 GenericQBuffer::User(QBuffer::new(self, buffer_info)) 144 } 145 GenericSupportedMemoryType::DmaBuf => { 146 GenericQBuffer::DmaBuf(QBuffer::new(self, buffer_info)) 147 } 148 }) 149 } 150 } 151 152 /// Any CAPTURE GenericQBuffer implements CaptureQueueable. 153 impl<Q> CaptureQueueable<GenericBufferHandles> for GenericQBuffer<Capture, Q> 154 where 155 Q: Deref<Target = Queue<Capture, BuffersAllocated<GenericBufferHandles>>>, 156 { queue_with_handles( self, handles: GenericBufferHandles, ) -> QueueResult<(), GenericBufferHandles>157 fn queue_with_handles( 158 self, 159 handles: GenericBufferHandles, 160 ) -> QueueResult<(), GenericBufferHandles> { 161 match self { 162 GenericQBuffer::Mmap(m) => m.queue_with_handles(handles), 163 GenericQBuffer::User(u) => u.queue_with_handles(handles), 164 GenericQBuffer::DmaBuf(d) => d.queue_with_handles(handles), 165 } 166 } 167 } 168 169 /// Any OUTPUT GenericQBuffer implements OutputQueueable. 170 impl<Q> OutputQueueable<GenericBufferHandles> for GenericQBuffer<Output, Q> 171 where 172 Q: Deref<Target = Queue<Output, BuffersAllocated<GenericBufferHandles>>>, 173 { queue_with_handles( self, handles: GenericBufferHandles, bytes_used: &[usize], ) -> QueueResult<(), GenericBufferHandles>174 fn queue_with_handles( 175 self, 176 handles: GenericBufferHandles, 177 bytes_used: &[usize], 178 ) -> QueueResult<(), GenericBufferHandles> { 179 match self { 180 GenericQBuffer::Mmap(m) => m.queue_with_handles(handles, bytes_used), 181 GenericQBuffer::User(u) => u.queue_with_handles(handles, bytes_used), 182 GenericQBuffer::DmaBuf(d) => d.queue_with_handles(handles, bytes_used), 183 } 184 } 185 } 186