rbroadlink/network/
wireless_connection.rs1use packed_struct::prelude::PackedStruct;
2
3use crate::network::util::checksum;
4
5#[derive(Debug)]
8pub enum WirelessConnection<'a> {
9 None(&'a str),
11
12 WEP(&'a str, &'a str),
14
15 WPA1(&'a str, &'a str),
17
18 WPA2(&'a str, &'a str),
20
21 WPA(&'a str, &'a str),
23}
24
25#[derive(PackedStruct, Debug)]
28#[packed_struct(bit_numbering = "msb0", endian = "lsb", size_bytes = "136")]
29pub struct WirelessConnectionMessage {
30 #[packed_field(bytes = "32:33")]
32 checksum: u16,
33
34 #[packed_field(bytes = "38")]
36 magic_constant: i8,
37
38 #[packed_field(bytes = "68:99")]
40 ssid: [u8; 32],
41
42 #[packed_field(bytes = "100:131")]
44 password: [u8; 32],
45
46 #[packed_field(bytes = "132")]
48 ssid_length: u8,
49
50 #[packed_field(bytes = "133")]
52 password_length: u8,
53
54 #[packed_field(bytes = "134")]
56 security_mode: u8,
57}
58
59impl WirelessConnection<'_> {
60 pub fn to_message(&self) -> Result<WirelessConnectionMessage, String> {
62 let empty_pass = "";
63 let (ssid, pass, security_mode) = match self {
64 WirelessConnection::None(ssid) => (ssid, &empty_pass, 0),
65 WirelessConnection::WEP(ssid, pass) => (ssid, pass, 1),
66 WirelessConnection::WPA1(ssid, pass) => (ssid, pass, 2),
67 WirelessConnection::WPA2(ssid, pass) => (ssid, pass, 3),
68 WirelessConnection::WPA(ssid, pass) => (ssid, pass, 4),
69 };
70
71 if ssid.len() > 32 {
73 return Err("Could not use provided SSID! SSID longer than 32 characters.".into());
74 }
75
76 let mut ssid_fixed = [0u8; 32];
78 let mut pass_fixed = [0u8; 32];
79 for (i, c) in ssid.as_bytes().iter().enumerate() {
80 ssid_fixed[i] = *c;
81 }
82 for (i, c) in pass.as_bytes().iter().enumerate() {
83 pass_fixed[i] = *c;
84 }
85
86 let mut msg = WirelessConnectionMessage {
88 checksum: 0,
90
91 magic_constant: 0x14,
93
94 ssid: ssid_fixed,
96 password: pass_fixed,
97 ssid_length: u8::try_from(ssid.len()).map_err(|e| {
98 format!(
99 "Could not use provided SSID! SSID is too long (max 32 characters). {}",
100 e
101 )
102 })?,
103 password_length: u8::try_from(pass.len()).map_err(|e| {
104 format!(
105 "Could not use provided password! Password is too long (max 32 characters). {}",
106 e
107 )
108 })?,
109
110 security_mode: security_mode,
111 };
112
113 msg.checksum = checksum(
115 &msg.pack()
116 .map_err(|e| format!("Could not pack WirelessConnectionMessage! {}", e))?,
117 );
118
119 return Ok(msg);
121 }
122}