1#[allow(dead_code)]
2use super::{codec, ids, Err};
3use generic_array::{ArrayLength, GenericArray};
4use heapless::String;
5use nom::{bytes::streaming::take, number::streaming, Input};
6
7pub struct GetMacAddress {}
9
10impl super::RPC for GetMacAddress {
11 type ReturnValue = String<18>;
12 type Error = i32;
13
14 fn header(&self, seq: u32) -> codec::Header {
15 codec::Header {
16 sequence: seq,
17 msg_type: ids::MsgType::Invocation,
18 service: ids::Service::Wifi,
19 request: ids::WifiRequest::GetMacAddress.into(),
20 }
21 }
22
23 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
24 let (data, hdr) = codec::Header::parse(data)?;
25 if hdr.msg_type != ids::MsgType::Reply
26 || hdr.service != ids::Service::Wifi
27 || hdr.request != ids::WifiRequest::GetMacAddress.into()
28 {
29 return Err(Err::NotOurs);
30 }
31
32 if data.input_len() < 18 {
33 return Err(Err::RPCErr(-1));
34 }
35 let mut mac: String<18> = String::new();
36 for b in data.take(17).iter_elements() {
37 mac.push(b as char).map_err(|_| Err::ResponseOverrun)?;
38 }
39
40 let (_, result) = streaming::le_u32(data.take_from(18))?;
41 if result != 0 {
42 Err(Err::RPCErr(result as i32))
43 } else {
44 Ok(mac)
45 }
46 }
47}
48
49pub struct IsScanning {}
51
52impl super::RPC for IsScanning {
53 type ReturnValue = bool;
54 type Error = ();
55
56 fn header(&self, seq: u32) -> codec::Header {
57 codec::Header {
58 sequence: seq,
59 msg_type: ids::MsgType::Invocation,
60 service: ids::Service::Wifi,
61 request: ids::WifiRequest::IsScanning.into(),
62 }
63 }
64
65 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
66 let (data, hdr) = codec::Header::parse(data)?;
67 if hdr.msg_type != ids::MsgType::Reply
68 || hdr.service != ids::Service::Wifi
69 || hdr.request != ids::WifiRequest::IsScanning.into()
70 {
71 return Err(Err::NotOurs);
72 }
73
74 if data.input_len() < 1 {
75 return Err(Err::RPCErr(()));
76 }
77 Ok(data.iter_elements().nth(0) != Some(0))
78 }
79}
80
81#[derive(Copy, Clone)]
83pub struct ScanResult {
84 pub ssid: super::SSID,
86 pub bssid: super::BSSID,
88 pub rssi: i16,
90 pub bss_type: super::BssType,
92 pub security: super::Security,
94 pub wps: super::WPS,
96 pub chan: u32,
98 pub band: super::Band,
100}
101
102impl core::fmt::Debug for ScanResult {
103 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104 #[allow(unused_unsafe)]
106 unsafe {
107 if self.ssid.len > 0 {
108 f.debug_struct("ScanResult")
109 .field("ssid", &self.ssid)
110 .field("bssid", &self.bssid)
111 .field("rssi", &self.rssi)
112 .field("type", &self.bss_type)
113 .field("security", &self.security)
114 .field("wps", &self.wps)
115 .field("channel", &self.chan)
116 .field("band", &self.band)
117 .finish()
118 } else {
119 f.debug_struct("ScanResult")
120 .field("bssid", &self.bssid)
121 .field("rssi", &self.rssi)
122 .field("type", &self.bss_type)
123 .field("security", &self.security)
124 .field("wps", &self.wps)
125 .field("channel", &self.chan)
126 .field("band", &self.band)
127 .finish()
128 }
129 }
130 }
131}
132
133impl Default for ScanResult {
134 fn default() -> Self {
135 Self {
136 ssid: super::SSID {
137 len: 0,
138 value: [0u8; 33],
139 },
140 bssid: super::BSSID([0u8; 6]),
141 rssi: 0,
142 bss_type: super::BssType::Any,
143 security: super::Security::empty(),
144 wps: super::WPS::Default,
145 chan: 0,
146 band: super::Band::_24Ghz,
147 }
148 }
149}
150
151pub struct ScanGetAP<N: ArrayLength<ScanResult>> {
154 m: core::marker::PhantomData<N>,
155}
156
157impl<N: ArrayLength<ScanResult>> ScanGetAP<N> {
158 pub fn new() -> Self {
159 Self {
160 m: core::marker::PhantomData,
161 }
162 }
163}
164
165impl<N: ArrayLength<ScanResult>> super::RPC for ScanGetAP<N> {
166 type ReturnValue = (GenericArray<ScanResult, N>, i32);
167 type Error = usize;
168
169 fn header(&self, seq: u32) -> codec::Header {
170 codec::Header {
171 sequence: seq,
172 msg_type: ids::MsgType::Invocation,
173 service: ids::Service::Wifi,
174 request: ids::WifiRequest::ScanGetAP.into(),
175 }
176 }
177
178 fn args(&self, buff: &mut heapless::Vec<u8, 64>) {
179 let num = N::to_u16().to_le_bytes();
180 buff.extend_from_slice(&num).ok();
181 }
182
183 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
184 let (data, hdr) = codec::Header::parse(data)?;
185 if hdr.msg_type != ids::MsgType::Reply
186 || hdr.service != ids::Service::Wifi
187 || hdr.request != ids::WifiRequest::ScanGetAP.into()
188 {
189 return Err(Err::NotOurs);
190 }
191
192 let (mut data, l) = streaming::le_u32(data)?; if l as usize != (62 * N::to_usize()) {
194 return Err(Err::ResponseOverrun);
195 }
196
197 use core::convert::TryInto;
198 let mut res = GenericArray::<ScanResult, N>::default();
199 for i in 0..N::to_usize() {
200 let (d, ssid_len) = streaming::le_u8(data)?;
201 let (d, ssid_data) = take(33usize)(d)?;
202 let (d, bssid) = take(6usize)(d)?;
203 let (d, rssi) = streaming::le_i16(d)?;
204 let (d, bss_type) = streaming::le_u32(d)?;
205 let (d, security) = streaming::le_u32(d)?;
206 let (d, wps) = streaming::le_u32(d)?;
207 let (d, chan) = streaming::le_u32(d)?;
208 let (d, band) = streaming::le_u32(d)?;
209
210 res[i] = ScanResult {
211 ssid: super::SSID {
212 len: ssid_len,
213 value: ssid_data.try_into().unwrap(),
214 },
215 bssid: super::BSSID(bssid.try_into().unwrap()),
216 rssi,
217 bss_type: bss_type.into(),
218 security: super::Security::from_bits_truncate(security),
219 wps: wps.into(),
220 chan,
221 band: band.into(),
222 };
223 data = d;
224 }
225
226 let (_, ret_val) = streaming::le_i32(data)?;
227 Ok((res, ret_val))
228 }
229}
230
231pub struct ScanGetNumAPs {}
233
234impl super::RPC for ScanGetNumAPs {
235 type ReturnValue = u16;
236 type Error = ();
237
238 fn header(&self, seq: u32) -> codec::Header {
239 codec::Header {
240 sequence: seq,
241 msg_type: ids::MsgType::Invocation,
242 service: ids::Service::Wifi,
243 request: ids::WifiRequest::ScanGetNumAPs.into(),
244 }
245 }
246
247 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
248 let (data, hdr) = codec::Header::parse(data)?;
249 if hdr.msg_type != ids::MsgType::Reply
250 || hdr.service != ids::Service::Wifi
251 || hdr.request != ids::WifiRequest::ScanGetNumAPs.into()
252 {
253 return Err(Err::NotOurs);
254 }
255
256 if data.input_len() < 2 {
257 return Err(Err::RPCErr(()));
258 }
259 let (_, num) = streaming::le_u16(data)?;
260 Ok(num)
261 }
262}
263
264pub struct ScanStart {}
266
267impl super::RPC for ScanStart {
268 type ReturnValue = i32;
269 type Error = ();
270
271 fn header(&self, seq: u32) -> codec::Header {
272 codec::Header {
273 sequence: seq,
274 msg_type: ids::MsgType::Invocation,
275 service: ids::Service::Wifi,
276 request: ids::WifiRequest::ScanStart.into(),
277 }
278 }
279
280 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
281 let (data, hdr) = codec::Header::parse(data)?;
282 if hdr.msg_type != ids::MsgType::Reply
283 || hdr.service != ids::Service::Wifi
284 || hdr.request != ids::WifiRequest::ScanStart.into()
285 {
286 return Err(Err::NotOurs);
287 }
288
289 let (_, num) = streaming::le_i32(data)?;
290 Ok(num)
291 }
292}
293
294pub struct WifiOn {
296 pub mode: super::WifiMode,
297}
298
299impl super::RPC for WifiOn {
300 type ReturnValue = i32;
301 type Error = ();
302
303 fn args(&self, buff: &mut heapless::Vec<u8, 64>) {
304 let mode = self.mode as u32;
305 buff.extend_from_slice(&mode.to_le_bytes()).ok();
306 }
307
308 fn header(&self, seq: u32) -> codec::Header {
309 codec::Header {
310 sequence: seq,
311 msg_type: ids::MsgType::Invocation,
312 service: ids::Service::Wifi,
313 request: ids::WifiRequest::TurnOn.into(),
314 }
315 }
316
317 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
318 let (data, hdr) = codec::Header::parse(data)?;
319 if hdr.msg_type != ids::MsgType::Reply
320 || hdr.service != ids::Service::Wifi
321 || hdr.request != ids::WifiRequest::TurnOn.into()
322 {
323 return Err(Err::NotOurs);
324 }
325
326 let (_, num) = streaming::le_i32(data)?;
327 Ok(num)
328 }
329}
330
331pub struct WifiOff {}
333
334impl super::RPC for WifiOff {
335 type ReturnValue = i32;
336 type Error = ();
337
338 fn header(&self, seq: u32) -> codec::Header {
339 codec::Header {
340 sequence: seq,
341 msg_type: ids::MsgType::Invocation,
342 service: ids::Service::Wifi,
343 request: ids::WifiRequest::TurnOff.into(),
344 }
345 }
346
347 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
348 let (data, hdr) = codec::Header::parse(data)?;
349 if hdr.msg_type != ids::MsgType::Reply
350 || hdr.service != ids::Service::Wifi
351 || hdr.request != ids::WifiRequest::TurnOff.into()
352 {
353 return Err(Err::NotOurs);
354 }
355
356 let (_, num) = streaming::le_i32(data)?;
357 Ok(num)
358 }
359}
360
361pub struct WifiConnect {
363 pub ssid: String<64>,
364 pub password: String<64>,
365 pub security: super::Security,
366 pub semaphore: u32,
368}
369
370impl super::RPC for WifiConnect {
371 type ReturnValue = i32;
372 type Error = ();
373
374 fn args(&self, buff: &mut heapless::Vec<u8, 64>) {
375 buff.extend_from_slice(&(self.ssid.len() as u32).to_le_bytes())
376 .ok();
377 buff.extend_from_slice(self.ssid.as_ref()).ok();
378
379 buff.push(if self.password.len() > 0 { 0u8 } else { 1u8 })
381 .ok();
382 if self.password.len() > 0 {
383 buff.extend_from_slice(&(self.password.len() as u32).to_le_bytes())
384 .ok();
385 buff.extend_from_slice(self.password.as_ref()).ok();
386 }
387
388 buff.extend_from_slice(&(self.security.bits()).to_le_bytes())
389 .ok();
390 buff.extend_from_slice(&(0u32.wrapping_sub(1)).to_le_bytes())
391 .ok(); buff.extend_from_slice(&(self.semaphore).to_le_bytes()).ok();
393 }
394
395 fn header(&self, seq: u32) -> codec::Header {
396 codec::Header {
397 sequence: seq,
398 msg_type: ids::MsgType::Invocation,
399 service: ids::Service::Wifi,
400 request: ids::WifiRequest::Connect.into(),
401 }
402 }
403
404 fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
405 let (data, hdr) = codec::Header::parse(data)?;
406 if hdr.msg_type != ids::MsgType::Reply
407 || hdr.service != ids::Service::Wifi
408 || hdr.request != ids::WifiRequest::Connect.into()
409 {
410 return Err(Err::NotOurs);
411 }
412
413 let (_, num) = streaming::le_i32(data)?;
414 Ok(num)
415 }
416}
417
418#[cfg(test)]
419mod tests {
420 use super::*;
421 use crate::RPC;
422
423 fn init() {
424 let _ = env_logger::builder().is_test(true).try_init();
425 }
426
427 #[test]
428 fn mac_address() {
429 init();
430 let mut input_bytes = [42u8; 36];
431
432 input_bytes[0] = 2; input_bytes[1] = 8; input_bytes[2] = 14; input_bytes[8..30].copy_from_slice(b"01:23:45:67:89:01x\0\0\0\0");
437
438 let parsed = GetMacAddress {}.parse(&input_bytes).expect("Parse failed");
439
440 assert_eq!(parsed, "01:23:45:67:89:01");
441 }
442}