hid_io_core/module/
mod.rs1pub mod daemonnode;
19pub mod displayserver;
20pub mod vhid;
21
22use crate::api;
23use crate::built_info;
24use crate::device;
25use crate::mailbox;
26use hid_io_protocol::commands::*;
27use hid_io_protocol::{HidIoCommandId, HidIoPacketType};
28use tokio_stream::{wrappers::BroadcastStream, StreamExt};
29
30const CMD_SIZE: usize = 200;
33
34struct CommandInterface {
37 src: mailbox::Address,
38 dst: mailbox::Address,
39 mailbox: mailbox::Mailbox,
40}
41
42impl
43 Commands<
44 { mailbox::HIDIO_PKT_BUF_DATA_SIZE },
45 { mailbox::HIDIO_PKT_BUF_DATA_SIZE - 1 },
46 { mailbox::HIDIO_PKT_BUF_DATA_SIZE - 2 },
47 { mailbox::HIDIO_PKT_BUF_DATA_SIZE - 4 },
48 CMD_SIZE,
49 > for CommandInterface
50{
51 fn tx_packetbuffer_send(
52 &mut self,
53 buf: &mut mailbox::HidIoPacketBuffer,
54 ) -> Result<(), CommandError> {
55 if let Some(rcvmsg) = self.mailbox.try_send_message(mailbox::Message {
56 src: self.src,
57 dst: self.dst,
58 data: buf.clone(),
59 })? {
60 self.rx_message_handling(rcvmsg.data)?;
62 }
63 Ok(())
64 }
65
66 fn h0000_supported_ids_cmd(
67 &mut self,
68 _data: h0000::Cmd,
69 ) -> Result<h0000::Ack<CMD_SIZE>, h0000::Nak> {
70 let ids = heapless::Vec::from_slice(&crate::supported_ids()).unwrap();
71 Ok(h0000::Ack { ids })
72 }
73
74 fn h0001_info_cmd(
75 &mut self,
76 data: h0001::Cmd,
77 ) -> Result<h0001::Ack<{ mailbox::HIDIO_PKT_BUF_DATA_SIZE - 1 }>, h0001::Nak> {
78 let mut ack = h0001::Ack::<{ mailbox::HIDIO_PKT_BUF_DATA_SIZE - 1 }> {
79 property: data.property,
80 os: h0001::OsType::Unknown,
81 number: 0,
82 string: heapless::String::from(""),
83 };
84 match data.property {
85 h0001::Property::MajorVersion => {
86 ack.number = built_info::PKG_VERSION_MAJOR.parse::<u16>().unwrap();
87 }
88 h0001::Property::MinorVersion => {
89 ack.number = built_info::PKG_VERSION_MINOR.parse::<u16>().unwrap();
90 }
91 h0001::Property::PatchVersion => {
92 ack.number = built_info::PKG_VERSION_PATCH.parse::<u16>().unwrap();
93 }
94 h0001::Property::OsType => {
95 ack.os = match built_info::CFG_OS {
96 "windows" => h0001::OsType::Windows,
97 "macos" => h0001::OsType::MacOs,
98 "ios" => h0001::OsType::Ios,
99 "linux" => h0001::OsType::Linux,
100 "android" => h0001::OsType::Android,
101 "freebsd" => h0001::OsType::FreeBsd,
102 "openbsd" => h0001::OsType::OpenBsd,
103 "netbsd" => h0001::OsType::NetBsd,
104 _ => h0001::OsType::Unknown,
105 };
106 }
107 h0001::Property::OsVersion => match sys_info::os_release() {
108 Ok(version) => {
109 ack.string = heapless::String::from(version.as_str());
110 }
111 Err(e) => {
112 error!("OS Release retrieval failed: {}", e);
113 return Err(h0001::Nak {
114 property: h0001::Property::OsVersion,
115 });
116 }
117 },
118 h0001::Property::HostSoftwareName => {
119 ack.string = heapless::String::from(built_info::PKG_NAME);
120 }
121 _ => {
122 return Err(h0001::Nak {
123 property: h0001::Property::Unknown,
124 });
125 }
126 }
127 Ok(ack)
128 }
129
130 fn h0030_openurl_cmd(
131 &mut self,
132 data: h0030::Cmd<{ mailbox::HIDIO_PKT_BUF_DATA_SIZE }>,
133 ) -> Result<h0030::Ack, h0030::Nak> {
134 debug!("Open url: {}", data.url);
135 let url = String::from(data.url.as_str());
136 if let Err(err) = open::that(url.clone()) {
137 error!("Failed to open url: {:?} - {:?}", url, err);
138 Err(h0030::Nak {})
139 } else {
140 Ok(h0030::Ack {})
141 }
142 }
143}
144
145pub fn supported_ids(recursive: bool) -> Vec<HidIoCommandId> {
148 let mut ids = vec![
149 HidIoCommandId::GetInfo,
150 HidIoCommandId::OpenUrl,
151 HidIoCommandId::SupportedIds,
152 ];
153 if recursive {
154 ids.extend(displayserver::supported_ids().iter().cloned());
155 }
156 ids
157}
158
159pub async fn initialize(mailbox: mailbox::Mailbox) {
165 info!("Initializing modules...");
166
167 let mailbox1 = mailbox.clone();
171 let data = tokio::spawn(async move {
172 let sender = mailbox1.clone().sender.clone();
174 let receiver = sender.clone().subscribe();
175 tokio::pin! {
176 let stream = BroadcastStream::new(receiver)
177 .filter(Result::is_ok).map(Result::unwrap)
178 .take_while(|msg|
179 msg.src != mailbox::Address::DropSubscription &&
180 msg.dst != mailbox::Address::CancelAllSubscriptions
181 )
182 .filter(|msg| msg.dst == mailbox::Address::Module || msg.dst == mailbox::Address::All)
183 .filter(|msg| supported_ids(false).contains(&msg.data.id))
184 .filter(|msg| msg.data.ptype == HidIoPacketType::Data || msg.data.ptype == HidIoPacketType::NaData);
185 }
186
187 while let Some(msg) = stream.next().await {
189 let mut intf = CommandInterface {
191 src: msg.dst, dst: msg.src, mailbox: mailbox1.clone(),
194 };
195 if let Err(err) = intf.rx_message_handling(msg.clone().data) {
196 warn!("Failed to process({:?}): {:?}", err, msg);
197 }
198 }
199 });
200
201 let mailbox2 = mailbox.clone();
203 let naks = tokio::spawn(async move {
204 let sender = mailbox2.clone().sender.clone();
206 let receiver = sender.clone().subscribe();
207 tokio::pin! {
208 let stream = BroadcastStream::new(receiver)
209 .filter(Result::is_ok).map(Result::unwrap)
210 .take_while(|msg|
211 msg.src != mailbox::Address::DropSubscription &&
212 msg.dst != mailbox::Address::CancelAllSubscriptions
213 )
214 .filter(|msg| !(
215 supported_ids(true).contains(&msg.data.id) ||
216 api::supported_ids().contains(&msg.data.id) ||
217 device::supported_ids(true).contains(&msg.data.id)
218 ))
219 .filter(|msg| msg.data.ptype == HidIoPacketType::Data || msg.data.ptype == HidIoPacketType::NaData);
220 }
221
222 while let Some(msg) = stream.next().await {
224 warn!("Unknown command ID: {:?} ({})", msg.data.id, msg.data.ptype);
225 if msg.data.ptype == HidIoPacketType::Data {
228 msg.send_nak(sender.clone(), vec![]);
229 }
230 }
231 });
232
233 let (_, _, _, _, _) = tokio::join!(
234 daemonnode::initialize(mailbox.clone()),
235 displayserver::initialize(mailbox.clone()),
236 naks,
237 data,
238 vhid::initialize(mailbox.clone()),
239 );
240}
241
242#[cfg(not(feature = "displayserver"))]
244mod displayserver {
245 use crate::mailbox;
246 use hid_io_protocol::HidIoCommandId;
247
248 pub async fn initialize(_mailbox: mailbox::Mailbox) {}
249 pub fn supported_ids() -> Vec<HidIoCommandId> {
250 vec![]
251 }
252}
253
254#[cfg(not(feature = "dev-capture"))]
256mod vhid {
257 use crate::mailbox;
258
259 pub async fn initialize(_mailbox: mailbox::Mailbox) {}
260}