1 use crate::{
2     device::queue::{
3         direction::{Capture, Direction, Output},
4         qbuf::{
5             CaptureQueueable, CaptureQueueableProvider, OutputQueueable, OutputQueueableProvider,
6             QBuffer, QueueResult,
7         },
8         BuffersAllocated, Queue,
9     },
10     memory::DmaBufHandle,
11 };
12 use crate::{
13     memory::MmapHandle,
14     memory::{BufferHandles, MemoryType, UserPtrHandle},
15 };
16 use std::{fmt::Debug, fs::File};
17 
18 /// Supported memory types for `GenericBufferHandles`.
19 /// TODO: This should be renamed to "DynamicBufferHandles", and be constructed
20 /// on-the-fly using a macro.
21 #[derive(Debug, Clone, Copy, PartialEq)]
22 pub enum GenericSupportedMemoryType {
23     Mmap,
24     UserPtr,
25     DmaBuf,
26 }
27 
28 impl From<GenericSupportedMemoryType> for MemoryType {
from(mem_type: GenericSupportedMemoryType) -> Self29     fn from(mem_type: GenericSupportedMemoryType) -> Self {
30         match mem_type {
31             GenericSupportedMemoryType::Mmap => MemoryType::Mmap,
32             GenericSupportedMemoryType::UserPtr => MemoryType::UserPtr,
33             GenericSupportedMemoryType::DmaBuf => MemoryType::DmaBuf,
34         }
35     }
36 }
37 
38 /// Buffer handle capable of holding either MMAP or UserPtr handles. Useful
39 /// for cases when we want to decide the memory type of a queue at runtime.
40 #[derive(Debug)]
41 pub enum GenericBufferHandles {
42     Mmap(Vec<MmapHandle>),
43     User(Vec<UserPtrHandle<Vec<u8>>>),
44     DmaBuf(Vec<DmaBufHandle<File>>),
45 }
46 
47 impl From<Vec<MmapHandle>> for GenericBufferHandles {
from(m: Vec<MmapHandle>) -> Self48     fn from(m: Vec<MmapHandle>) -> Self {
49         Self::Mmap(m)
50     }
51 }
52 
53 impl From<Vec<UserPtrHandle<Vec<u8>>>> for GenericBufferHandles {
from(u: Vec<UserPtrHandle<Vec<u8>>>) -> Self54     fn from(u: Vec<UserPtrHandle<Vec<u8>>>) -> Self {
55         Self::User(u)
56     }
57 }
58 
59 impl From<Vec<DmaBufHandle<File>>> for GenericBufferHandles {
from(d: Vec<DmaBufHandle<File>>) -> Self60     fn from(d: Vec<DmaBufHandle<File>>) -> Self {
61         Self::DmaBuf(d)
62     }
63 }
64 
65 impl BufferHandles for GenericBufferHandles {
66     type SupportedMemoryType = GenericSupportedMemoryType;
67 
len(&self) -> usize68     fn len(&self) -> usize {
69         match self {
70             GenericBufferHandles::Mmap(m) => m.len(),
71             GenericBufferHandles::User(u) => u.len(),
72             GenericBufferHandles::DmaBuf(d) => d.len(),
73         }
74     }
75 
fill_v4l2_plane(&self, index: usize, plane: &mut crate::bindings::v4l2_plane)76     fn fill_v4l2_plane(&self, index: usize, plane: &mut crate::bindings::v4l2_plane) {
77         match self {
78             GenericBufferHandles::Mmap(m) => m.fill_v4l2_plane(index, plane),
79             GenericBufferHandles::User(u) => u.fill_v4l2_plane(index, plane),
80             GenericBufferHandles::DmaBuf(d) => d.fill_v4l2_plane(index, plane),
81         }
82     }
83 }
84 
85 /// A QBuffer that holds either MMAP or UserPtr handles, depending on which
86 /// memory type has been selected for the queue at runtime.
87 pub enum GenericQBuffer<'a, D: Direction> {
88     Mmap(QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>),
89     User(QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>),
90     DmaBuf(QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>),
91 }
92 
93 impl<'a, D: Direction> From<QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>>
94     for GenericQBuffer<'a, D>
95 {
from(qb: QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>) -> Self96     fn from(qb: QBuffer<'a, D, Vec<MmapHandle>, GenericBufferHandles>) -> Self {
97         GenericQBuffer::Mmap(qb)
98     }
99 }
100 
101 impl<'a, D: Direction> From<QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>>
102     for GenericQBuffer<'a, D>
103 {
from(qb: QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>) -> Self104     fn from(qb: QBuffer<'a, D, Vec<UserPtrHandle<Vec<u8>>>, GenericBufferHandles>) -> Self {
105         GenericQBuffer::User(qb)
106     }
107 }
108 
109 impl<'a, D: Direction> From<QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>>
110     for GenericQBuffer<'a, D>
111 {
from(qb: QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>) -> Self112     fn from(qb: QBuffer<'a, D, Vec<DmaBufHandle<File>>, GenericBufferHandles>) -> Self {
113         GenericQBuffer::DmaBuf(qb)
114     }
115 }
116 
117 /// Any CAPTURE GenericQBuffer implements CaptureQueueable.
118 impl CaptureQueueable<GenericBufferHandles> for GenericQBuffer<'_, Capture> {
queue_with_handles( self, handles: GenericBufferHandles, ) -> QueueResult<(), GenericBufferHandles>119     fn queue_with_handles(
120         self,
121         handles: GenericBufferHandles,
122     ) -> QueueResult<(), GenericBufferHandles> {
123         match self {
124             GenericQBuffer::Mmap(m) => m.queue_with_handles(handles),
125             GenericQBuffer::User(u) => u.queue_with_handles(handles),
126             GenericQBuffer::DmaBuf(d) => d.queue_with_handles(handles),
127         }
128     }
129 }
130 
131 /// Any OUTPUT GenericQBuffer implements OutputQueueable.
132 impl OutputQueueable<GenericBufferHandles> for GenericQBuffer<'_, Output> {
queue_with_handles( self, handles: GenericBufferHandles, bytes_used: &[usize], ) -> QueueResult<(), GenericBufferHandles>133     fn queue_with_handles(
134         self,
135         handles: GenericBufferHandles,
136         bytes_used: &[usize],
137     ) -> QueueResult<(), GenericBufferHandles> {
138         match self {
139             GenericQBuffer::Mmap(m) => m.queue_with_handles(handles, bytes_used),
140             GenericQBuffer::User(u) => u.queue_with_handles(handles, bytes_used),
141             GenericQBuffer::DmaBuf(d) => d.queue_with_handles(handles, bytes_used),
142         }
143     }
144 }
145 
146 impl<'a> CaptureQueueableProvider<'a, GenericBufferHandles>
147     for Queue<Capture, BuffersAllocated<GenericBufferHandles>>
148 {
149     type Queueable = GenericQBuffer<'a, Capture>;
150 }
151 
152 impl<'a> OutputQueueableProvider<'a, GenericBufferHandles>
153     for Queue<Output, BuffersAllocated<GenericBufferHandles>>
154 {
155     type Queueable = GenericQBuffer<'a, Output>;
156 }
157