1use std::{ffi::CStr, marker::PhantomData, ptr::NonNull};
2
3use libcamera_sys::*;
4use thiserror::Error;
5
6use crate::{
7 control_value::{ControlValue, ControlValueError},
8 controls::{self, ControlId},
9 properties::{self, PropertyId},
10 utils::{UniquePtr, UniquePtrTarget},
11};
12
13#[derive(Debug, Error)]
14pub enum ControlError {
15 #[error("Control id {0} not found")]
16 NotFound(u32),
17 #[error("Control value error: {0}")]
18 ValueError(#[from] ControlValueError),
19}
20
21pub trait ControlEntry:
22 Clone + Into<ControlValue> + TryFrom<ControlValue, Error = ControlValueError> + core::fmt::Debug
23{
24 const ID: u32;
25}
26
27pub trait Control: ControlEntry {}
28pub trait Property: ControlEntry {}
29
30pub trait DynControlEntry: core::fmt::Debug {
32 fn id(&self) -> u32;
33 fn value(&self) -> ControlValue;
34}
35
36impl<T: ControlEntry> DynControlEntry for T {
37 fn id(&self) -> u32 {
38 Self::ID
39 }
40
41 fn value(&self) -> ControlValue {
42 self.clone().into()
43 }
44}
45
46#[repr(transparent)]
47pub struct ControlInfo(libcamera_control_info_t);
48
49impl ControlInfo {
50 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_t>) -> &'a mut Self {
51 &mut *(ptr.as_ptr() as *mut Self)
53 }
54
55 pub(crate) fn ptr(&self) -> *const libcamera_control_info_t {
56 &self.0 as *const libcamera_control_info_t
58 }
59
60 pub fn min(&self) -> ControlValue {
61 unsafe {
62 ControlValue::read(NonNull::new(libcamera_control_info_min(self.ptr().cast_mut()).cast_mut()).unwrap())
63 .unwrap()
64 }
65 }
66
67 pub fn max(&self) -> ControlValue {
68 unsafe {
69 ControlValue::read(NonNull::new(libcamera_control_info_max(self.ptr().cast_mut()).cast_mut()).unwrap())
70 .unwrap()
71 }
72 }
73
74 pub fn def(&self) -> ControlValue {
75 unsafe {
76 ControlValue::read(NonNull::new(libcamera_control_info_def(self.ptr().cast_mut()).cast_mut()).unwrap())
77 .unwrap()
78 }
79 }
80
81 pub fn values(&self) -> Vec<ControlValue> {
82 unsafe {
83 let mut size: usize = 0;
84 let values_ptr = libcamera_control_info_values(self.ptr(), &mut size as *mut usize);
85
86 if values_ptr.is_null() || size == 0 {
87 return Vec::new();
88 }
89
90 let control_value_size = libcamera_control_value_size();
92
93 let base_ptr = values_ptr as *const u8;
95
96 let mut control_values = Vec::with_capacity(size);
97 for i in 0..size {
98 let offset = i * control_value_size;
100 let val_ptr = base_ptr.add(offset) as *const libcamera_control_value_t;
101
102 if val_ptr.is_null() {
103 eprintln!("ControlValue at index {i} is null");
104 continue;
105 }
106
107 match ControlValue::read(NonNull::new(val_ptr.cast_mut()).unwrap()) {
109 Ok(control_val) => control_values.push(control_val),
110 Err(e) => {
111 eprintln!("Failed to read ControlValue at index {i}: {e:?}");
112 }
113 }
114 }
115
116 control_values
117 }
118 }
119}
120
121impl core::fmt::Debug for ControlInfo {
122 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123 f.debug_struct("ControlInfo")
124 .field("min", &self.min())
125 .field("max", &self.max())
126 .field("def", &self.def())
127 .field("values", &self.values())
128 .finish()
129 }
130}
131
132#[repr(transparent)]
133pub struct ControlInfoMap(libcamera_control_info_map_t);
134
135impl ControlInfoMap {
136 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_info_map_t>) -> &'a mut Self {
137 &mut *(ptr.as_ptr() as *mut Self)
139 }
140
141 pub(crate) fn ptr(&self) -> *const libcamera_control_info_map_t {
142 &self.0 as *const libcamera_control_info_map_t
144 }
145
146 pub fn at(&self, key: u32) -> Result<&ControlInfo, ControlError> {
147 unsafe {
148 let ptr = NonNull::new(libcamera_control_info_map_at(self.ptr().cast_mut(), key).cast_mut());
149 match ptr {
150 Some(ptr) => Ok(ControlInfo::from_ptr(ptr)),
151 None => Err(ControlError::NotFound(key)),
152 }
153 }
154 }
155
156 pub fn count(&self, key: u32) -> usize {
157 unsafe { libcamera_control_info_map_count(self.ptr().cast_mut(), key) }
158 }
159
160 pub fn find(&self, key: u32) -> Result<&ControlInfo, ControlError> {
161 unsafe {
162 let ptr = NonNull::new(libcamera_control_info_map_find(self.ptr().cast_mut(), key).cast_mut());
163
164 match ptr {
165 Some(ptr) => Ok(ControlInfo::from_ptr(ptr)),
166 None => Err(ControlError::NotFound(key)),
167 }
168 }
169 }
170
171 pub fn size(&self) -> usize {
172 unsafe { libcamera_control_info_map_size(self.ptr().cast_mut()) }
173 }
174}
175
176impl<'a> IntoIterator for &'a ControlInfoMap {
177 type Item = (u32, &'a ControlInfo);
178 type IntoIter = ControlInfoMapIter<'a>;
179
180 fn into_iter(self) -> Self::IntoIter {
181 ControlInfoMapIter::new(self).expect("Failed to create ControlInfoMap iterator")
182 }
183}
184
185impl core::fmt::Debug for ControlInfoMap {
186 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
187 let mut dm = f.debug_map();
188 for (key, value) in self.into_iter() {
189 match ControlId::try_from(key) {
190 Ok(id) => dm.entry(&id, value),
191 Err(_) => dm.entry(&key, value),
192 };
193 }
194 dm.finish()
195 }
196}
197
198#[repr(transparent)]
199pub struct ControlList(libcamera_control_list_t);
200
201impl UniquePtrTarget for ControlList {
202 unsafe fn ptr_new() -> *mut Self {
203 libcamera_control_list_create() as *mut Self
204 }
205
206 unsafe fn ptr_drop(ptr: *mut Self) {
207 libcamera_control_list_destroy(ptr as *mut libcamera_control_list_t)
208 }
209}
210
211impl ControlList {
212 pub fn new() -> UniquePtr<Self> {
213 UniquePtr::new()
214 }
215
216 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
217 &mut *(ptr.as_ptr() as *mut Self)
219 }
220
221 pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
222 &self.0 as *const libcamera_control_list_t
224 }
225
226 pub fn get<C: Control>(&self) -> Result<C, ControlError> {
227 let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
228 .ok_or(ControlError::NotFound(C::ID))?;
229
230 let val = unsafe { ControlValue::read(val_ptr) }?;
231 Ok(C::try_from(val)?)
232 }
233
234 pub fn set<C: Control>(&mut self, val: C) -> Result<(), ControlError> {
239 let ctrl_val: ControlValue = val.into();
240
241 unsafe {
242 let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
243 ctrl_val.write(val_ptr);
244 libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
245 libcamera_control_value_destroy(val_ptr.as_ptr());
246 }
247
248 Ok(())
249 }
250
251 pub fn set_raw(&mut self, id: u32, val: ControlValue) -> Result<(), ControlError> {
256 unsafe {
257 let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
258 val.write(val_ptr);
259 libcamera_control_list_set(self.ptr().cast_mut(), id as _, val_ptr.as_ptr());
260 libcamera_control_value_destroy(val_ptr.as_ptr());
261 }
262
263 Ok(())
264 }
265
266 pub fn get_raw(&mut self, id: u32) -> Result<ControlValue, ControlError> {
267 let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), id as _).cast_mut() })
268 .ok_or(ControlError::NotFound(id))?;
269
270 let val = unsafe { ControlValue::read(val_ptr) }?;
271 Ok(val)
272 }
273}
274
275impl<'d> IntoIterator for &'d ControlList {
276 type Item = (u32, ControlValue);
277
278 type IntoIter = ControlListRefIterator<'d>;
279
280 fn into_iter(self) -> Self::IntoIter {
281 ControlListRefIterator {
282 it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
283 _phantom: Default::default(),
284 }
285 }
286}
287
288impl core::fmt::Debug for ControlList {
289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290 let mut map = f.debug_map();
291 for (id, val) in self.into_iter() {
292 match ControlId::try_from(id) {
293 Ok(id) => match controls::make_dyn(id, val.clone()) {
295 Ok(val) => map.entry(&id, &val),
296 Err(_) => map.entry(&id, &val),
297 },
298 Err(_) => map.entry(&id, &val),
300 };
301 }
302 map.finish()
303 }
304}
305
306#[repr(transparent)]
307pub struct PropertyList(libcamera_control_list_t);
308
309impl PropertyList {
310 pub(crate) unsafe fn from_ptr<'a>(ptr: NonNull<libcamera_control_list_t>) -> &'a mut Self {
311 &mut *(ptr.as_ptr() as *mut Self)
313 }
314
315 pub(crate) fn ptr(&self) -> *const libcamera_control_list_t {
316 &self.0 as *const libcamera_control_list_t
318 }
319
320 pub fn get<C: Property>(&self) -> Result<C, ControlError> {
321 let val_ptr = NonNull::new(unsafe { libcamera_control_list_get(self.ptr().cast_mut(), C::ID as _).cast_mut() })
322 .ok_or(ControlError::NotFound(C::ID))?;
323
324 let val = unsafe { ControlValue::read(val_ptr) }?;
325
326 Ok(C::try_from(val)?)
327 }
328
329 pub fn set<C: Property>(&mut self, val: C) -> Result<(), ControlError> {
334 let ctrl_val: ControlValue = val.into();
335
336 unsafe {
337 let val_ptr = NonNull::new(libcamera_control_value_create()).unwrap();
338 ctrl_val.write(val_ptr);
339 libcamera_control_list_set(self.ptr().cast_mut(), C::ID as _, val_ptr.as_ptr());
340 libcamera_control_value_destroy(val_ptr.as_ptr());
341 }
342
343 Ok(())
344 }
345}
346
347impl<'d> IntoIterator for &'d PropertyList {
348 type Item = (u32, ControlValue);
349
350 type IntoIter = ControlListRefIterator<'d>;
351
352 fn into_iter(self) -> Self::IntoIter {
353 ControlListRefIterator {
354 it: NonNull::new(unsafe { libcamera_control_list_iter(self.ptr().cast_mut()) }).unwrap(),
355 _phantom: Default::default(),
356 }
357 }
358}
359
360impl core::fmt::Debug for PropertyList {
361 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
362 let mut map = f.debug_map();
363 for (id, val) in self.into_iter() {
364 match PropertyId::try_from(id) {
365 Ok(id) => match properties::make_dyn(id, val.clone()) {
367 Ok(val) => map.entry(&id, &val),
368 Err(_) => map.entry(&id, &val),
369 },
370 Err(_) => map.entry(&id, &val),
372 };
373 }
374 map.finish()
375 }
376}
377
378pub struct ControlListRefIterator<'d> {
379 it: NonNull<libcamera_control_list_iter_t>,
380 _phantom: PhantomData<&'d ()>,
381}
382
383impl Iterator for ControlListRefIterator<'_> {
384 type Item = (u32, ControlValue);
385
386 fn next(&mut self) -> Option<Self::Item> {
387 if unsafe { libcamera_control_list_iter_end(self.it.as_ptr()) } {
388 None
389 } else {
390 let id = unsafe { libcamera_control_list_iter_id(self.it.as_ptr()) };
391 let val_ptr =
392 NonNull::new(unsafe { libcamera_control_list_iter_value(self.it.as_ptr()).cast_mut() }).unwrap();
393 let val = unsafe { ControlValue::read(val_ptr) }.unwrap();
394
395 unsafe { libcamera_control_list_iter_next(self.it.as_ptr()) };
396
397 Some((id, val))
398 }
399 }
400}
401
402impl Drop for ControlListRefIterator<'_> {
403 fn drop(&mut self) {
404 unsafe { libcamera_control_list_iter_destroy(self.it.as_ptr()) }
405 }
406}
407
408pub struct ControlInfoMapIter<'a> {
409 iter: *mut libcamera_control_info_map_iter_t,
410 marker: PhantomData<&'a libcamera_control_info_map_t>,
411}
412
413impl<'a> ControlInfoMapIter<'a> {
414 pub fn new(map: &'a ControlInfoMap) -> Option<Self> {
415 unsafe {
416 let iter = libcamera_control_info_map_iter_create(map.ptr());
417 if iter.is_null() {
418 None
419 } else {
420 Some(ControlInfoMapIter {
421 iter,
422 marker: PhantomData,
423 })
424 }
425 }
426 }
427}
428
429impl<'a> Iterator for ControlInfoMapIter<'a> {
430 type Item = (u32, &'a ControlInfo);
431
432 fn next(&mut self) -> Option<Self::Item> {
433 unsafe {
434 if libcamera_control_info_map_iter_has_next(self.iter) {
435 let key = libcamera_control_info_map_iter_key(self.iter);
436 let value_ptr = libcamera_control_info_map_iter_value(self.iter);
437 if value_ptr.is_null() {
438 None
439 } else {
440 let control_info = &*(value_ptr as *const ControlInfo);
441 libcamera_control_info_map_iter_next(self.iter);
442 Some((key, control_info))
443 }
444 } else {
445 None
446 }
447 }
448 }
449}
450
451impl<'a> Drop for ControlInfoMapIter<'a> {
452 fn drop(&mut self) {
453 unsafe {
454 libcamera_control_info_map_iter_destroy(self.iter);
455 }
456 }
457}
458
459impl ControlId {
460 pub fn name(&self) -> String {
461 unsafe { CStr::from_ptr(libcamera_control_name_from_id(self.id())) }
462 .to_str()
463 .unwrap()
464 .into()
465 }
466}
467
468impl PropertyId {
469 pub fn name(&self) -> String {
470 unsafe { CStr::from_ptr(libcamera_property_name_from_id(self.id())) }
471 .to_str()
472 .unwrap()
473 .into()
474 }
475}