1use crate::prelude_internal::*;
6
7#[derive(Debug, Copy, Clone, Eq, Ord, PartialOrd, PartialEq, num_derive::FromPrimitive)]
11pub enum JoinerState {
12 Idle = OT_JOINER_STATE_IDLE as isize,
14
15 Discover = OT_JOINER_STATE_DISCOVER as isize,
17
18 Connect = OT_JOINER_STATE_CONNECT as isize,
20
21 Connected = OT_JOINER_STATE_CONNECTED as isize,
23
24 Entrust = OT_JOINER_STATE_ENTRUST as isize,
26
27 Joined = OT_JOINER_STATE_JOINED as isize,
29}
30
31impl From<otJoinerState> for JoinerState {
32 fn from(x: otJoinerState) -> Self {
33 use num::FromPrimitive;
34 Self::from_u32(x).unwrap_or_else(|| panic!("Unknown otJoinerState value: {x}"))
35 }
36}
37
38impl From<JoinerState> for otJoinerState {
39 fn from(x: JoinerState) -> Self {
40 x as otJoinerState
41 }
42}
43
44pub trait Joiner {
48 #[allow(clippy::too_many_arguments)]
51 fn joiner_start<'a, F: FnOnce(Result) + 'a>(
52 &self,
53 pskd: &str,
54 provisioning_url: Option<&str>,
55 vendor_name: Option<&str>,
56 vendor_model: Option<&str>,
57 vendor_sw_version: Option<&str>,
58 vendor_data: Option<&str>,
59 callback: F,
60 ) -> Result;
61
62 fn joiner_stop(&self);
65
66 fn joiner_get_state(&self) -> JoinerState;
69
70 fn joiner_start_async(
75 &self,
76 pskd: &str,
77 provisioning_url: Option<&str>,
78 vendor_name: Option<&str>,
79 vendor_model: Option<&str>,
80 vendor_sw_version: Option<&str>,
81 vendor_data: Option<&str>,
82 ) -> futures::channel::oneshot::Receiver<Result> {
83 use futures::channel::oneshot::*;
84 let (sender, receiver) = channel();
85 let sender = std::sync::Arc::new(fuchsia_sync::Mutex::new(Some(sender)));
86 let sender_clone = sender.clone();
87 if let Err(err) = self.joiner_start(
88 pskd,
89 provisioning_url,
90 vendor_name,
91 vendor_model,
92 vendor_sw_version,
93 vendor_data,
94 move |result| {
95 let _ = sender_clone
96 .lock()
97 .take()
98 .and_then(move |x: Sender<Result>| x.send(result).ok());
99 },
100 ) {
101 sender.lock().take().and_then(move |x: Sender<Result>| x.send(Err(err)).ok());
102 }
103 receiver
104 }
105}
106
107impl<T: Joiner + Boxable> Joiner for ot::Box<T> {
108 fn joiner_start<'a, F: FnOnce(Result) + 'a>(
109 &self,
110 pskd: &str,
111 provisioning_url: Option<&str>,
112 vendor_name: Option<&str>,
113 vendor_model: Option<&str>,
114 vendor_sw_version: Option<&str>,
115 vendor_data: Option<&str>,
116 callback: F,
117 ) -> Result {
118 self.as_ref().joiner_start(
119 pskd,
120 provisioning_url,
121 vendor_name,
122 vendor_model,
123 vendor_sw_version,
124 vendor_data,
125 callback,
126 )
127 }
128
129 fn joiner_stop(&self) {
130 self.as_ref().joiner_stop()
131 }
132
133 fn joiner_get_state(&self) -> JoinerState {
134 self.as_ref().joiner_get_state()
135 }
136}
137
138impl Joiner for Instance {
139 fn joiner_start<'a, F: FnOnce(Result) + 'a>(
140 &self,
141 pskd: &str,
142 provisioning_url: Option<&str>,
143 vendor_name: Option<&str>,
144 vendor_model: Option<&str>,
145 vendor_sw_version: Option<&str>,
146 vendor_data: Option<&str>,
147 callback: F,
148 ) -> Result {
149 unsafe extern "C" fn _ot_joiner_callback(
150 error: otError,
151 context: *mut ::std::os::raw::c_void,
152 ) {
153 trace!("_ot_joiner_callback");
154
155 let instance = Instance::ref_from_ot_ptr(context as *mut otInstance).unwrap();
157
158 if let Some(func) = instance.borrow_backing().joiner_fn.take() {
159 func(Error::from(error).into_result());
160 }
161 }
162
163 let pskd = CString::new(pskd).map_err(|_| Error::InvalidArgs)?;
164 let provisioning_url =
165 provisioning_url.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
166 let vendor_name =
167 vendor_name.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
168 let vendor_model =
169 vendor_model.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
170 let vendor_sw_version =
171 vendor_sw_version.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
172 let vendor_data =
173 vendor_data.map(CString::new).transpose().map_err(|_| Error::InvalidArgs)?;
174
175 let pskd_ptr = pskd.as_bytes_with_nul().as_ptr() as *const ::std::os::raw::c_char;
176 let provisioning_url_ptr =
177 provisioning_url.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
178 as *const ::std::os::raw::c_char;
179 let vendor_name_ptr =
180 vendor_name.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
181 as *const ::std::os::raw::c_char;
182 let vendor_model_ptr =
183 vendor_model.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
184 as *const ::std::os::raw::c_char;
185 let vendor_sw_version_ptr =
186 vendor_sw_version.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
187 as *const ::std::os::raw::c_char;
188 let vendor_data_ptr =
189 vendor_data.as_ref().map(|x| x.as_bytes_with_nul().as_ptr()).unwrap_or(null())
190 as *const ::std::os::raw::c_char;
191
192 let fn_box = Some(Box::new(callback) as Box<dyn FnOnce(Result) + 'a>);
193
194 let ret = Error::from(unsafe {
195 self.borrow_backing().joiner_fn.set(std::mem::transmute::<
201 Option<Box<dyn FnOnce(Result) + 'a>>,
202 Option<Box<dyn FnOnce(Result) + 'static>>,
203 >(fn_box));
204
205 otJoinerStart(
206 self.as_ot_ptr(),
207 pskd_ptr,
208 provisioning_url_ptr,
209 vendor_name_ptr,
210 vendor_model_ptr,
211 vendor_sw_version_ptr,
212 vendor_data_ptr,
213 Some(_ot_joiner_callback),
214 self.as_ot_ptr() as *mut ::std::os::raw::c_void,
215 )
216 })
217 .into_result();
218
219 if ret.is_err() {
220 self.borrow_backing().joiner_fn.take();
223 }
224
225 ret
226 }
227
228 fn joiner_stop(&self) {
229 unsafe { otJoinerStop(self.as_ot_ptr()) }
230
231 self.borrow_backing().joiner_fn.take();
233 }
234
235 fn joiner_get_state(&self) -> JoinerState {
236 unsafe { otJoinerGetState(self.as_ot_ptr()) }.into()
237 }
238}