1use std::ptr::NonNull;
2
3use libcamera_control_type::*;
4use libcamera_sys::*;
5use smallvec::{smallvec, SmallVec};
6use thiserror::Error;
7
8use crate::geometry::{Point, Rectangle, Size};
9
10#[derive(Error, Debug)]
11pub enum ControlValueError {
12 #[error("Expected type {expected}, found {found}")]
14 InvalidType { expected: u32, found: u32 },
15 #[error("Unknown control type {0}")]
17 UnknownType(u32),
18 #[error("Expected {expected} elements, found {found}")]
20 InvalidLength { expected: usize, found: usize },
21 #[error("Unknown enum variant {0:?}")]
23 UnknownVariant(ControlValue),
24}
25#[derive(Debug, Clone)]
27pub enum ControlValue {
28 None,
29 Bool(SmallVec<[bool; 1]>),
30 Byte(SmallVec<[u8; 1]>),
31 Uint16(SmallVec<[u16; 1]>),
32 Uint32(SmallVec<[u32; 1]>),
33 Int32(SmallVec<[i32; 1]>),
34 Int64(SmallVec<[i64; 1]>),
35 Float(SmallVec<[f32; 1]>),
36 String(SmallVec<[String; 1]>),
37 Rectangle(SmallVec<[Rectangle; 1]>),
38 Size(SmallVec<[Size; 1]>),
39 Point(SmallVec<[Point; 1]>),
41}
42
43macro_rules! impl_control_value {
44 ($p:path, $type:ty) => {
45 impl From<$type> for ControlValue {
46 fn from(val: $type) -> Self {
47 $p(smallvec![val])
48 }
49 }
50
51 impl TryFrom<ControlValue> for $type {
52 type Error = ControlValueError;
53
54 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
55 match value {
56 $p(mut val) => {
57 if val.len() == 1 {
58 Ok(val.pop().unwrap())
59 } else {
60 Err(ControlValueError::InvalidLength {
61 expected: 1,
62 found: val.len(),
63 })
64 }
65 }
66 _ => Err(ControlValueError::InvalidType {
67 expected: $p(Default::default()).ty(),
69 found: value.ty(),
70 }),
71 }
72 }
73 }
74 };
75}
76
77impl_control_value!(ControlValue::Bool, bool);
78impl_control_value!(ControlValue::Byte, u8);
79impl_control_value!(ControlValue::Uint16, u16);
80impl_control_value!(ControlValue::Uint32, u32);
81impl_control_value!(ControlValue::Int32, i32);
82impl_control_value!(ControlValue::Int64, i64);
83impl_control_value!(ControlValue::Float, f32);
84impl_control_value!(ControlValue::Rectangle, Rectangle);
85impl_control_value!(ControlValue::Size, Size);
86impl_control_value!(ControlValue::Point, Point);
87
88macro_rules! impl_control_value_vec {
89 ($p:path, $type:ty) => {
90 impl From<Vec<$type>> for ControlValue {
91 fn from(val: Vec<$type>) -> Self {
92 $p(SmallVec::from_vec(val))
93 }
94 }
95
96 impl TryFrom<ControlValue> for Vec<$type> {
97 type Error = ControlValueError;
98
99 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
100 match value {
101 $p(val) => Ok(val.into_vec()),
102 _ => Err(ControlValueError::InvalidType {
103 expected: $p(Default::default()).ty(),
105 found: value.ty(),
106 }),
107 }
108 }
109 }
110 };
111}
112
113impl_control_value_vec!(ControlValue::Bool, bool);
114impl_control_value_vec!(ControlValue::Byte, u8);
115impl_control_value_vec!(ControlValue::Uint16, u16);
116impl_control_value_vec!(ControlValue::Uint32, u32);
117impl_control_value_vec!(ControlValue::Int32, i32);
118impl_control_value_vec!(ControlValue::Int64, i64);
119impl_control_value_vec!(ControlValue::Float, f32);
120impl_control_value_vec!(ControlValue::Rectangle, Rectangle);
121impl_control_value_vec!(ControlValue::Size, Size);
122impl_control_value_vec!(ControlValue::Point, Point);
123
124macro_rules! impl_control_value_array {
125 ($p:path, $type:ty) => {
126 impl<const N: usize> From<[$type; N]> for ControlValue {
127 fn from(val: [$type; N]) -> Self {
128 $p(SmallVec::from_slice(&val))
129 }
130 }
131
132 impl<const N: usize> TryFrom<ControlValue> for [$type; N] {
133 type Error = ControlValueError;
134
135 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
136 match value {
137 $p(val) => {
138 Ok(val
139 .into_vec()
140 .try_into()
141 .map_err(|e: Vec<$type>| ControlValueError::InvalidLength {
142 expected: N,
143 found: e.len(),
144 })?)
145 }
146 _ => Err(ControlValueError::InvalidType {
147 expected: $p(Default::default()).ty(),
149 found: value.ty(),
150 }),
151 }
152 }
153 }
154
155 impl<const N: usize, const M: usize> From<[[$type; M]; N]> for ControlValue {
156 fn from(val: [[$type; M]; N]) -> Self {
157 $p(SmallVec::from_slice(&unsafe {
158 core::slice::from_raw_parts(val.as_ptr().cast(), N * M)
159 }))
160 }
161 }
162
163 impl<const N: usize, const M: usize> TryFrom<ControlValue> for [[$type; M]; N] {
164 type Error = ControlValueError;
165
166 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
167 match value {
168 $p(val) => {
169 if val.len() == N * M {
170 let mut iter = val.into_iter();
171 Ok([[(); M]; N].map(|a| a.map(|_| iter.next().unwrap())))
172 } else {
173 Err(ControlValueError::InvalidLength {
174 expected: N * M,
175 found: val.len(),
176 })
177 }
178 }
179 _ => Err(ControlValueError::InvalidType {
180 expected: $p(Default::default()).ty(),
182 found: value.ty(),
183 }),
184 }
185 }
186 }
187 };
188}
189
190impl_control_value_array!(ControlValue::Bool, bool);
191impl_control_value_array!(ControlValue::Byte, u8);
192impl_control_value_array!(ControlValue::Uint16, u16);
193impl_control_value_array!(ControlValue::Uint32, u32);
194impl_control_value_array!(ControlValue::Int32, i32);
195impl_control_value_array!(ControlValue::Int64, i64);
196impl_control_value_array!(ControlValue::Float, f32);
197impl_control_value_array!(ControlValue::Rectangle, Rectangle);
198impl_control_value_array!(ControlValue::Size, Size);
199impl_control_value_array!(ControlValue::Point, Point);
200
201impl From<String> for ControlValue {
202 fn from(val: String) -> Self {
203 Self::String(smallvec![val])
204 }
205}
206
207impl TryFrom<ControlValue> for String {
208 type Error = ControlValueError;
209
210 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
211 match value {
212 ControlValue::String(mut v) => {
213 if v.len() == 1 {
214 Ok(v.pop().unwrap())
215 } else {
216 Err(ControlValueError::InvalidLength {
217 expected: 1,
218 found: v.len(),
219 })
220 }
221 }
222 _ => Err(ControlValueError::InvalidType {
223 expected: libcamera_control_type::LIBCAMERA_CONTROL_TYPE_STRING,
224 found: value.ty(),
225 }),
226 }
227 }
228}
229
230impl From<Vec<String>> for ControlValue {
231 fn from(val: Vec<String>) -> Self {
232 ControlValue::String(SmallVec::from_vec(val))
233 }
234}
235
236impl TryFrom<ControlValue> for Vec<String> {
237 type Error = ControlValueError;
238
239 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
240 match value {
241 ControlValue::String(v) => Ok(v.into_vec()),
242 _ => Err(ControlValueError::InvalidType {
243 expected: libcamera_control_type::LIBCAMERA_CONTROL_TYPE_STRING,
244 found: value.ty(),
245 }),
246 }
247 }
248}
249
250impl ControlValue {
251 pub(crate) unsafe fn read(val: NonNull<libcamera_control_value_t>) -> Result<Self, ControlValueError> {
252 let ty = unsafe { libcamera_control_value_type(val.as_ptr()) };
253 let num_elements = unsafe { libcamera_control_value_num_elements(val.as_ptr()) };
254 let data = unsafe { libcamera_control_value_get(val.as_ptr()) };
255
256 match ty {
257 LIBCAMERA_CONTROL_TYPE_NONE => Ok(Self::None),
258 LIBCAMERA_CONTROL_TYPE_BOOL => {
259 let slice = core::slice::from_raw_parts(data as *const bool, num_elements);
260 Ok(Self::Bool(SmallVec::from_slice(slice)))
261 }
262 LIBCAMERA_CONTROL_TYPE_BYTE => {
263 let slice = core::slice::from_raw_parts(data as *const u8, num_elements);
264 Ok(Self::Byte(SmallVec::from_slice(slice)))
265 }
266 LIBCAMERA_CONTROL_TYPE_UINT16 => {
267 let slice = core::slice::from_raw_parts(data as *const u16, num_elements);
268 Ok(Self::Uint16(SmallVec::from_slice(slice)))
269 }
270 LIBCAMERA_CONTROL_TYPE_UINT32 => {
271 let slice = core::slice::from_raw_parts(data as *const u32, num_elements);
272 Ok(Self::Uint32(SmallVec::from_slice(slice)))
273 }
274 LIBCAMERA_CONTROL_TYPE_INT32 => {
275 let slice = core::slice::from_raw_parts(data as *const i32, num_elements);
276 Ok(Self::Int32(SmallVec::from_slice(slice)))
277 }
278 LIBCAMERA_CONTROL_TYPE_INT64 => {
279 let slice = core::slice::from_raw_parts(data as *const i64, num_elements);
280 Ok(Self::Int64(SmallVec::from_slice(slice)))
281 }
282 LIBCAMERA_CONTROL_TYPE_FLOAT => {
283 let slice = core::slice::from_raw_parts(data as *const f32, num_elements);
284 Ok(Self::Float(SmallVec::from_slice(slice)))
285 }
286 LIBCAMERA_CONTROL_TYPE_STRING => {
287 let slice = core::slice::from_raw_parts(data as *const u8, num_elements);
288 let mut parts = Vec::new();
290 let mut start = 0usize;
291 for (idx, b) in slice.iter().enumerate() {
292 if *b == 0 {
293 parts.push(&slice[start..idx]);
294 start = idx + 1;
295 }
296 }
297 if start < slice.len() {
298 parts.push(&slice[start..]);
299 }
300 if parts.is_empty() {
301 parts.push(&[]);
302 }
303 let strings = parts
304 .into_iter()
305 .filter_map(|p| core::str::from_utf8(p).ok())
306 .map(|s| s.to_string())
307 .collect();
308 Ok(Self::String(strings))
309 }
310 LIBCAMERA_CONTROL_TYPE_RECTANGLE => {
311 let slice = core::slice::from_raw_parts(data as *const libcamera_rectangle_t, num_elements);
312 Ok(Self::Rectangle(SmallVec::from_iter(
313 slice.iter().map(|r| Rectangle::from(*r)),
314 )))
315 }
316 LIBCAMERA_CONTROL_TYPE_SIZE => {
317 let slice = core::slice::from_raw_parts(data as *const libcamera_size_t, num_elements);
318 Ok(Self::Size(SmallVec::from_iter(slice.iter().map(|r| Size::from(*r)))))
319 }
320 LIBCAMERA_CONTROL_TYPE_POINT => {
321 let slice = core::slice::from_raw_parts(data as *const libcamera_point_t, num_elements);
322 Ok(Self::Point(SmallVec::from_iter(slice.iter().map(|r| Point::from(*r)))))
323 }
324 _ => Err(ControlValueError::UnknownType(ty)),
325 }
326 }
327
328 pub(crate) unsafe fn write(&self, val: NonNull<libcamera_control_value_t>) {
329 let mut tmp_string_buf: Vec<u8> = Vec::new();
330 let (data, len) = match self {
331 ControlValue::None => (core::ptr::null(), 0),
332 ControlValue::Bool(v) => (v.as_ptr().cast(), v.len()),
333 ControlValue::Byte(v) => (v.as_ptr().cast(), v.len()),
334 ControlValue::Uint16(v) => (v.as_ptr().cast(), v.len()),
335 ControlValue::Uint32(v) => (v.as_ptr().cast(), v.len()),
336 ControlValue::Int32(v) => (v.as_ptr().cast(), v.len()),
337 ControlValue::Int64(v) => (v.as_ptr().cast(), v.len()),
338 ControlValue::Float(v) => (v.as_ptr().cast(), v.len()),
339 ControlValue::String(v) => {
340 if v.len() <= 1 {
341 let s = v.first().map(|s| s.as_bytes()).unwrap_or(&[]);
342 tmp_string_buf.extend_from_slice(s);
343 } else {
344 tmp_string_buf.extend_from_slice(v.join("\0").as_bytes());
345 }
346 (tmp_string_buf.as_ptr(), tmp_string_buf.len())
347 }
348 ControlValue::Rectangle(v) => (v.as_ptr().cast(), v.len()),
349 ControlValue::Size(v) => (v.as_ptr().cast(), v.len()),
350 ControlValue::Point(v) => (v.as_ptr().cast(), v.len()),
351 };
352
353 let is_array = matches!(self, ControlValue::String(_)) || len != 1;
356
357 libcamera_control_value_set(val.as_ptr(), self.ty(), data.cast(), is_array, len as _);
358 }
359
360 pub fn ty(&self) -> u32 {
361 use libcamera_control_type::*;
362 match self {
363 ControlValue::None => LIBCAMERA_CONTROL_TYPE_NONE,
364 ControlValue::Bool(_) => LIBCAMERA_CONTROL_TYPE_BOOL,
365 ControlValue::Byte(_) => LIBCAMERA_CONTROL_TYPE_BYTE,
366 ControlValue::Uint16(_) => LIBCAMERA_CONTROL_TYPE_UINT16,
367 ControlValue::Uint32(_) => LIBCAMERA_CONTROL_TYPE_UINT32,
368 ControlValue::Int32(_) => LIBCAMERA_CONTROL_TYPE_INT32,
369 ControlValue::Int64(_) => LIBCAMERA_CONTROL_TYPE_INT64,
370 ControlValue::Float(_) => LIBCAMERA_CONTROL_TYPE_FLOAT,
371 ControlValue::String(_) => LIBCAMERA_CONTROL_TYPE_STRING,
372 ControlValue::Rectangle(_) => LIBCAMERA_CONTROL_TYPE_RECTANGLE,
373 ControlValue::Size(_) => LIBCAMERA_CONTROL_TYPE_SIZE,
374 ControlValue::Point(_) => LIBCAMERA_CONTROL_TYPE_POINT,
375 }
376 }
377}
378
379#[derive(Error, Debug)]
380pub enum ControlTypeError {
381 #[error("Unknown control type {0}")]
383 UnknownType(u32),
384}
385
386#[derive(Debug, Clone)]
387#[repr(u32)]
388pub enum ControlType {
389 None = LIBCAMERA_CONTROL_TYPE_NONE,
390 Bool = LIBCAMERA_CONTROL_TYPE_BOOL,
391 Byte = LIBCAMERA_CONTROL_TYPE_BYTE,
392 Uint16 = LIBCAMERA_CONTROL_TYPE_UINT16,
393 Uint32 = LIBCAMERA_CONTROL_TYPE_UINT32,
394 Int32 = LIBCAMERA_CONTROL_TYPE_INT32,
395 Int64 = LIBCAMERA_CONTROL_TYPE_INT64,
396 Float = LIBCAMERA_CONTROL_TYPE_FLOAT,
397 String = LIBCAMERA_CONTROL_TYPE_STRING,
398 Rectangle = LIBCAMERA_CONTROL_TYPE_RECTANGLE,
399 Size = LIBCAMERA_CONTROL_TYPE_SIZE,
400 Point = LIBCAMERA_CONTROL_TYPE_POINT,
401}
402
403impl TryFrom<u32> for ControlType {
404 type Error = ControlTypeError;
405
406 fn try_from(value: u32) -> Result<Self, Self::Error> {
407 use libcamera_control_type::*;
408 match value {
409 LIBCAMERA_CONTROL_TYPE_NONE => Ok(ControlType::None),
410 LIBCAMERA_CONTROL_TYPE_BOOL => Ok(ControlType::Bool),
411 LIBCAMERA_CONTROL_TYPE_BYTE => Ok(ControlType::Byte),
412 LIBCAMERA_CONTROL_TYPE_UINT16 => Ok(ControlType::Uint16),
413 LIBCAMERA_CONTROL_TYPE_UINT32 => Ok(ControlType::Uint32),
414 LIBCAMERA_CONTROL_TYPE_INT32 => Ok(ControlType::Int32),
415 LIBCAMERA_CONTROL_TYPE_INT64 => Ok(ControlType::Int64),
416 LIBCAMERA_CONTROL_TYPE_FLOAT => Ok(ControlType::Float),
417 LIBCAMERA_CONTROL_TYPE_STRING => Ok(ControlType::String),
418 LIBCAMERA_CONTROL_TYPE_RECTANGLE => Ok(ControlType::Rectangle),
419 LIBCAMERA_CONTROL_TYPE_SIZE => Ok(ControlType::Size),
420 LIBCAMERA_CONTROL_TYPE_POINT => Ok(ControlType::Point),
421 unknown => Err(ControlTypeError::UnknownType(unknown)),
422 }
423 }
424}
425
426impl From<ControlType> for u32 {
427 fn from(control_type: ControlType) -> Self {
428 control_type as u32
429 }
430}
431
432impl From<&ControlValue> for ControlType {
433 fn from(control_value: &ControlValue) -> Self {
434 match control_value {
435 ControlValue::None => ControlType::None,
436 ControlValue::Bool(_) => ControlType::Bool,
437 ControlValue::Byte(_) => ControlType::Byte,
438 ControlValue::Uint16(_) => ControlType::Uint16,
439 ControlValue::Uint32(_) => ControlType::Uint32,
440 ControlValue::Int32(_) => ControlType::Int32,
441 ControlValue::Int64(_) => ControlType::Int64,
442 ControlValue::Float(_) => ControlType::Float,
443 ControlValue::String(_) => ControlType::String,
444 ControlValue::Rectangle(_) => ControlType::Rectangle,
445 ControlValue::Size(_) => ControlType::Size,
446 ControlValue::Point(_) => ControlType::Point,
447 }
448 }
449}
450
451impl TryFrom<ControlValue> for ControlType {
452 type Error = ControlTypeError;
453
454 fn try_from(value: ControlValue) -> Result<Self, Self::Error> {
455 Ok(ControlType::from(&value))
456 }
457}