1use std::{collections::HashMap, ffi::CStr, marker::PhantomData, ptr::NonNull};
2
3use libcamera_control_direction::*;
4use libcamera_sys::*;
5use num_enum::{IntoPrimitive, TryFromPrimitive};
6use thiserror::Error;
7
8use crate::{
9 control_value::{ControlType, ControlValue, ControlValueError},
10 controls::{self, ControlId},
11 properties::{self, PropertyId},
12 utils::{UniquePtr, UniquePtrTarget},
13};
14
15#[derive(Debug, Error)]
16pub enum ControlError {
17 #[error("Control id {0} not found")]
18 NotFound(u32),
19 #[error("Control value error: {0}")]
20 ValueError(#[from] ControlValueError),
21}
22
23pub trait ControlEntry:
24 Clone + Into<ControlValue> + TryFrom<ControlValue, Error = ControlValueError> + core::fmt::Debug
25{
26 const ID: u32;
27}
28
29pub trait Control: ControlEntry {}
30pub trait Property: ControlEntry {}
31
32pub trait DynControlEntry: core::fmt::Debug {
34 fn id(&self) -> u32;
35 fn value(&self) -> ControlValue;
36}
37
38impl<T: ControlEntry> DynControlEntry for T {
39 fn id(&self) -> u32 {
40 Self::ID
41 }
42
43 fn value(&self) -> ControlValue {
44 self.clone().into()
45 }
46}
47
48#[repr(transparent)]
49pub struct ControlInfo(libcamera_control_info_t);
50
51impl ControlInfo {
52 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_t>) -> &'a mut Self {
53 &mut *(ptr.as_ptr() as *mut Self)
55 }
56
57 pub(crate) fn ptr(&self) -> *const libcamera_control_info_t {
58 &self.0 as *const libcamera_control_info_t
60 }
61
62 pub fn min(&self) -> ControlValue {
63 unsafe {
64 ControlValue::read(NonNull::new(libcamera_control_info_min(self.ptr().cast_mut()).cast_mut()).unwrap())
65 .unwrap()
66 }
67 }
68
69 pub fn max(&self) -> ControlValue {
70 unsafe {
71 ControlValue::read(NonNull::new(libcamera_control_info_max(self.ptr().cast_mut()).cast_mut()).unwrap())
72 .unwrap()
73 }
74 }
75
76 pub fn def(&self) -> ControlValue {
77 unsafe {
78 ControlValue::read(NonNull::new(libcamera_control_info_def(self.ptr().cast_mut()).cast_mut()).unwrap())
79 .unwrap()
80 }
81 }
82
83 pub fn values(&self) -> Vec<ControlValue> {
84 unsafe {
85 let mut size: usize = 0;
86 let values_ptr = libcamera_control_info_values(self.ptr(), &mut size as *mut usize);
87
88 if values_ptr.is_null() || size == 0 {
89 return Vec::new();
90 }
91
92 let control_value_size = libcamera_control_value_size();
94
95 let base_ptr = values_ptr as *const u8;
97
98 let mut control_values = Vec::with_capacity(size);
99 for i in 0..size {
100 let offset = i * control_value_size;
102 let val_ptr = base_ptr.add(offset) as *const libcamera_control_value_t;
103
104 if val_ptr.is_null() {
105 eprintln!("ControlValue at index {i} is null");
106 continue;
107 }
108
109 match ControlValue::read(NonNull::new(val_ptr.cast_mut()).unwrap()) {
111 Ok(control_val) => control_values.push(control_val),
112 Err(e) => {
113 eprintln!("Failed to read ControlValue at index {i}: {e:?}");
114 }
115 }
116 }
117
118 control_values
119 }
120 }
121}
122
123impl core::fmt::Debug for ControlInfo {
124 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
125 f.debug_struct("ControlInfo")
126 .field("min", &self.min())
127 .field("max", &self.max())
128 .field("def", &self.def())
129 .field("values", &self.values())
130 .finish()
131 }
132}
133
134#[repr(transparent)]
135pub struct ControlInfoMap(libcamera_control_info_map_t);
136
137impl ControlInfoMap {
138 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_map_t>) -> &'a mut Self {
139 &mut *(ptr.as_ptr() as *mut Self)
141 }
142
143 pub(crate) fn ptr(&self) -> *const libcamera_control_info_map_t {
144 &self.0 as *const libcamera_control_info_map_t
146 }
147
148 pub fn at(&self, key: u32) -> Result<&ControlInfo, ControlError> {
149 unsafe {
150 let ptr = NonNull::new(libcamera_control_info_map_at(self.ptr().cast_mut(), key).cast_mut());
151 match ptr {
152 Some(ptr) => Ok(ControlInfo::from_ptr(ptr)),
153 None => Err(ControlError::NotFound(key)),
154 }
155 }
156 }
157
158 pub fn count(&self, key: u32) -> usize {
159 unsafe { libcamera_control_info_map_count(self.ptr().cast_mut(), key) }
160 }
161
162 pub fn find(&self, key: u32) -> Result<&ControlInfo, ControlError> {
163 unsafe {
164 let ptr = NonNull::new(libcamera_control_info_map_find(self.ptr().cast_mut(), key).cast_mut());
165
166 match ptr {
167 Some(ptr) => Ok(ControlInfo::from_ptr(ptr)),
168 None => Err(ControlError::NotFound(key)),
169 }
170 }
171 }
172
173 pub fn size(&self) -> usize {
174 unsafe { libcamera_control_info_map_size(self.ptr().cast_mut()) }
175 }
176}
177
178impl<'a> IntoIterator for &'a ControlInfoMap {
179 type Item = (u32, &'a ControlInfo);
180 type IntoIter = ControlInfoMapIter<'a>;
181
182 fn into_iter(self) -> Self::IntoIter {
183 ControlInfoMapIter::new(self).expect("Failed to create ControlInfoMap iterator")
184 }
185}
186
187impl core::fmt::Debug for ControlInfoMap {
188 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189 let mut dm = f.debug_map();
190 for (key, value) in self.into_iter() {
191 match ControlId::try_from(key) {
192 Ok(id) => dm.entry(&id.name(), value),
193 Err(_) => dm.entry(&key, value),
194 };
195 }
196 dm.finish()
197 }
198}
199
200#[repr(transparent)]
201pub struct ControlList(libcamera_control_list_t);
202
203impl UniquePtrTarget for ControlList {
204 unsafe fn ptr_new() -> *mut Self {
205 libcamera_control_list_create() as *mut Self
206 }
207
208 unsafe fn ptr_drop(ptr: *mut Self) {
209 libcamera_control_list_destroy(ptr as *mut libcamera_control_list_t)
210 }
211}
212
213impl ControlList {
214 pub fn new() -> UniquePtr<Self> {
215 UniquePtr::new()
216 }
217
218 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
219 &mut *(ptr.as_ptr() as *mut Self)
221 }
222
223 pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
224 &self.0 as *const libcamera_control_list_t
226 }
227
228 pub fn get<C: Control>(&self) -> Result<C, ControlError> {
229 let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
230 .ok_or(ControlError::NotFound(C::ID))?;
231
232 let val = unsafe { ControlValue::read(val_ptr) }?;
233 Ok(C::try_from(val)?)
234 }
235
236 pub fn set<C: Control>(&mut self, val: C) -> Result<(), ControlError> {
241 let ctrl_val: ControlValue = val.into();
242
243 unsafe {
244 let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
245 ctrl_val.write(val_ptr);
246 libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
247 libcamera_control_value_destroy(val_ptr.as_ptr());
248 }
249
250 Ok(())
251 }
252
253 pub fn set_raw(&mut self, id: u32, val: ControlValue) -> Result<(), ControlError> {
258 unsafe {
259 let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
260 val.write(val_ptr);
261 libcamera_control_list_set(self.ptr().cast_mut(), id as _, val_ptr.as_ptr());
262 libcamera_control_value_destroy(val_ptr.as_ptr());
263 }
264
265 Ok(())
266 }
267
268 pub fn get_raw(&mut self, id: u32) -> Result<ControlValue, ControlError> {
269 let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), id as _).cast_mut() })
270 .ok_or(ControlError::NotFound(id))?;
271
272 let val = unsafe { ControlValue::read(val_ptr) }?;
273 Ok(val)
274 }
275}
276
277impl<'d> IntoIterator for &'d ControlList {
278 type Item = (u32, ControlValue);
279
280 type IntoIter = ControlListRefIterator<'d>;
281
282 fn into_iter(self) -> Self::IntoIter {
283 ControlListRefIterator {
284 it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
285 _phantom: Default::default(),
286 }
287 }
288}
289
290impl core::fmt::Debug for ControlList {
291 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
292 let mut map = f.debug_map();
293 for (id, val) in self.into_iter() {
294 match ControlId::try_from(id) {
295 Ok(id) => match controls::make_dyn(id, val.clone()) {
297 Ok(val) => map.entry(&id, &val),
298 Err(_) => map.entry(&id, &val),
299 },
300 Err(_) => map.entry(&id, &val),
302 };
303 }
304 map.finish()
305 }
306}
307
308#[repr(transparent)]
309pub struct PropertyList(libcamera_control_list_t);
310
311impl PropertyList {
312 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
313 &mut *(ptr.as_ptr() as *mut Self)
315 }
316
317 pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
318 &self.0 as *const libcamera_control_list_t
320 }
321
322 pub fn get<C: Property>(&self) -> Result<C, ControlError> {
323 let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
324 .ok_or(ControlError::NotFound(C::ID))?;
325
326 let val = unsafe { ControlValue::read(val_ptr) }?;
327
328 Ok(C::try_from(val)?)
329 }
330
331 pub fn set<C: Property>(&mut self, val: C) -> Result<(), ControlError> {
336 let ctrl_val: ControlValue = val.into();
337
338 unsafe {
339 let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
340 ctrl_val.write(val_ptr);
341 libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
342 libcamera_control_value_destroy(val_ptr.as_ptr());
343 }
344
345 Ok(())
346 }
347}
348
349impl<'d> IntoIterator for &'d PropertyList {
350 type Item = (u32, ControlValue);
351
352 type IntoIter = ControlListRefIterator<'d>;
353
354 fn into_iter(self) -> Self::IntoIter {
355 ControlListRefIterator {
356 it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
357 _phantom: Default::default(),
358 }
359 }
360}
361
362impl core::fmt::Debug for PropertyList {
363 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
364 let mut map = f.debug_map();
365 for (id, val) in self.into_iter() {
366 match PropertyId::try_from(id) {
367 Ok(id) => match properties::make_dyn(id, val.clone()) {
369 Ok(val) => map.entry(&id, &val),
370 Err(_) => map.entry(&id, &val),
371 },
372 Err(_) => map.entry(&id, &val),
374 };
375 }
376 map.finish()
377 }
378}
379
380pub struct ControlListRefIterator<'d> {
381 it: NonNull<libcamera_control_list_iter_t>,
382 _phantom: PhantomData<&'d ()>,
383}
384
385impl Iterator for ControlListRefIterator<'_> {
386 type Item = (u32, ControlValue);
387
388 fn next(&mut self) -> Option<Self::Item> {
389 if unsafe { libcamera_control_list_iter_end(self.it.as_ptr()) } {
390 None
391 } else {
392 let id = unsafe { libcamera_control_list_iter_id(self.it.as_ptr()) };
393 let val_ptr =
394 NonNull::new(unsafe { libcamera_control_list_iter_value(self.it.as_ptr()).cast_mut() }).unwrap();
395 let val = unsafe { ControlValue::read(val_ptr) }.unwrap();
396
397 unsafe { libcamera_control_list_iter_next(self.it.as_ptr()) };
398
399 Some((id, val))
400 }
401 }
402}
403
404impl Drop for ControlListRefIterator<'_> {
405 fn drop(&mut self) {
406 unsafe { libcamera_control_list_iter_destroy(self.it.as_ptr()) }
407 }
408}
409
410pub struct ControlInfoMapIter<'a> {
411 iter: *mut libcamera_control_info_map_iter_t,
412 marker: PhantomData<&'a libcamera_control_info_map_t>,
413}
414
415impl<'a> ControlInfoMapIter<'a> {
416 pub fn new(map: &'a ControlInfoMap) -> Option<Self> {
417 unsafe {
418 let iter = libcamera_control_info_map_iter_create(map.ptr());
419 if iter.is_null() {
420 None
421 } else {
422 Some(ControlInfoMapIter {
423 iter,
424 marker: PhantomData,
425 })
426 }
427 }
428 }
429}
430
431impl<'a> Iterator for ControlInfoMapIter<'a> {
432 type Item = (u32, &'a ControlInfo);
433
434 fn next(&mut self) -> Option<Self::Item> {
435 unsafe {
436 if libcamera_control_info_map_iter_has_next(self.iter) {
437 let key = libcamera_control_info_map_iter_key(self.iter);
438 let value_ptr = libcamera_control_info_map_iter_value(self.iter);
439 if value_ptr.is_null() {
440 None
441 } else {
442 let control_info = &*(value_ptr as *const ControlInfo);
443 libcamera_control_info_map_iter_next(self.iter);
444 Some((key, control_info))
445 }
446 } else {
447 None
448 }
449 }
450 }
451}
452
453impl<'a> Drop for ControlInfoMapIter<'a> {
454 fn drop(&mut self) {
455 unsafe {
456 libcamera_control_info_map_iter_destroy(self.iter);
457 }
458 }
459}
460
461pub struct ControlIdEnumeratorsIter<'a> {
462 iter: *mut libcamera_control_id_enumerators_iter_t,
463 marker: PhantomData<&'a ControlId>,
464}
465
466impl<'a> ControlIdEnumeratorsIter<'a> {
467 fn new(id: &'a ControlId) -> Option<Self> {
468 unsafe {
469 let iter = libcamera_control_id_enumerators_iter_create(id.as_ptr());
470 if iter.is_null() {
471 None
472 } else {
473 Some(ControlIdEnumeratorsIter {
474 iter,
475 marker: PhantomData,
476 })
477 }
478 }
479 }
480}
481
482impl Iterator for ControlIdEnumeratorsIter<'_> {
483 type Item = (i32, String);
484
485 fn next(&mut self) -> Option<Self::Item> {
486 unsafe {
487 if libcamera_control_id_enumerators_iter_has_next(self.iter) {
488 let key = libcamera_control_id_enumerators_iter_key(self.iter);
489 let val_ptr = libcamera_control_id_enumerators_iter_value(self.iter);
490 if val_ptr.is_null() {
491 None
492 } else {
493 let name = CStr::from_ptr(val_ptr).to_string_lossy().into_owned();
494 libcamera_control_id_enumerators_iter_next(self.iter);
495 Some((key, name))
496 }
497 } else {
498 None
499 }
500 }
501 }
502}
503
504impl Drop for ControlIdEnumeratorsIter<'_> {
505 fn drop(&mut self) {
506 unsafe {
507 libcamera_control_id_enumerators_iter_destroy(self.iter);
508 }
509 }
510}
511
512#[derive(Debug, Clone, Copy, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
513#[repr(u32)]
514pub enum ControlDirection {
515 In = LIBCAMERA_CONTROL_DIRECTION_IN,
517 Out = LIBCAMERA_CONTROL_DIRECTION_OUT,
519 InOut = LIBCAMERA_CONTROL_DIRECTION_IN | LIBCAMERA_CONTROL_DIRECTION_OUT,
521}
522
523impl ControlId {
524 pub fn name(&self) -> String {
525 unsafe { CStr::from_ptr(libcamera_control_name_from_id(self.id())) }
526 .to_str()
527 .unwrap()
528 .into()
529 }
530
531 fn as_ptr(&self) -> *mut libcamera_control_id_t {
532 let ptr = unsafe { libcamera_control_from_id(self.id()) as *mut libcamera_control_id_t };
533 assert!(!ptr.is_null(), "libcamera_control_from_id returned null");
534 ptr
535 }
536
537 pub fn vendor(&self) -> String {
538 unsafe {
539 let ctrl = self.as_ptr();
540 if ctrl.is_null() {
541 String::new()
542 } else {
543 let ptr = libcamera_control_id_vendor(ctrl);
544 CStr::from_ptr(ptr).to_string_lossy().to_string()
545 }
546 }
547 }
548
549 pub fn control_type(&self) -> ControlType {
550 let raw = unsafe { libcamera_control_id_type(self.as_ptr()) } as u32;
551 ControlType::try_from(raw).expect("Unknown ControlType")
552 }
553
554 pub fn direction(&self) -> ControlDirection {
555 let raw = unsafe { libcamera_control_id_direction(self.as_ptr()) } as u32;
556 ControlDirection::try_from(raw).expect("Unknown libcamera_control_direction value")
557 }
558
559 pub fn is_input(&self) -> bool {
560 unsafe { libcamera_control_id_is_input(self.as_ptr()) }
561 }
562
563 pub fn is_output(&self) -> bool {
564 unsafe { libcamera_control_id_is_output(self.as_ptr()) }
565 }
566
567 pub fn is_array(&self) -> bool {
568 unsafe { libcamera_control_id_is_array(self.as_ptr()) }
569 }
570
571 pub fn size(&self) -> usize {
572 unsafe { libcamera_control_id_size(self.as_ptr()) }
573 }
574
575 pub fn enumerators(&self) -> Option<ControlIdEnumeratorsIter<'_>> {
576 ControlIdEnumeratorsIter::new(self)
577 }
578
579 pub fn enumerators_map(&self) -> HashMap<i32, String> {
580 match self.enumerators() {
581 Some(iter) => iter.collect(),
582 None => HashMap::new(),
583 }
584 }
585
586 pub fn from_id(id: u32) -> Option<Self> {
587 ControlId::try_from(id).ok()
588 }
589}
590
591impl PropertyId {
592 pub fn name(&self) -> String {
593 unsafe { CStr::from_ptr(libcamera_property_name_from_id(self.id())) }
594 .to_str()
595 .unwrap()
596 .into()
597 }
598}