1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
macro_rules! impl_pin {
    ($type:ident, $type_str:expr, $hal_fn:expr, $hal_fn_str:expr, $storage:ty, $storage_str:expr) => {
        #[doc = $type_str]
        #[doc = "HAL pin."]
        #[doc = ""]
        #[doc = "Equivalent to the [`"]
        #[doc = $hal_fn_str]
        #[doc = "`] HAL function, backed internally by a [`"]
        #[doc = $storage_str]
        #[doc = "`]."]
        #[derive(Debug, PartialEq)]
        pub struct $type {
            name: String,
            storage: *mut *mut $storage,
        }

        impl $crate::hal_pin::HalPin for $type {
            type Storage = $storage;

            fn name(&self) -> &str {
                &self.name
            }

            fn storage(&self) -> Result<&mut Self::Storage, $crate::error::StorageError> {
                if self.storage.is_null() {
                    Err($crate::error::StorageError::Null)
                } else {
                    Ok(unsafe { &mut **self.storage })
                }
            }

            fn register_pin(
                full_pin_name: &str,
                direction: $crate::hal_pin::PinDirection,
                component_id: i32,
            ) -> Result<Self, $crate::error::PinRegisterError> {
                if full_pin_name.len() > linuxcnc_hal_sys::HAL_NAME_LEN as usize {
                    return Err($crate::error::PinRegisterError::NameLength);
                }

                let storage = Self::allocate_storage().map_err($crate::error::PinRegisterError::Storage)?;

                let ret = unsafe {
                    $hal_fn(
                        full_pin_name.as_ptr() as *const i8,
                        direction as i32,
                        storage as *mut *mut $storage,
                        component_id,
                    )
                };

                match ret {
                    x if x == -(linuxcnc_hal_sys::EINVAL as i32) => {
                        Err($crate::error::PinRegisterError::Invalid)
                    }
                    x if x == -(linuxcnc_hal_sys::EPERM as i32) => Err($crate::error::PinRegisterError::LockedHal),
                    x if x == -(linuxcnc_hal_sys::ENOMEM as i32) => {
                        Err($crate::error::PinRegisterError::Memory)
                    }
                    0 => {
                        debug!("Make pin {} returned {}", full_pin_name, ret);

                        Ok(Self {
                            name: full_pin_name.to_string(),
                            storage,
                        })
                    }
                    code => unreachable!("Hit unreachable error code {}", code),
                }
            }
        }

        impl Drop for $type {
            fn drop(&mut self) {
                debug!("Drop HalPinF64 {}", self.name);
            }
        }
    };
}