1use std::{
4 collections::HashMap,
5 ffi::{OsStr, OsString},
6 fmt, fs,
7 io::{Error, ErrorKind, Result},
8 os::unix::prelude::{OsStrExt, OsStringExt},
9 path::{Component, Path, PathBuf},
10 sync::{Arc, Mutex, MutexGuard, Once, OnceLock},
11};
12
13use crate::{function::register_remove_handlers, trim_os_str};
14
15pub trait Function: fmt::Debug + Send + Sync + 'static {
17 fn driver(&self) -> OsString;
19
20 fn dir(&self) -> FunctionDir;
22
23 fn register(&self) -> Result<()>;
25
26 fn pre_removal(&self) -> Result<()> {
28 Ok(())
29 }
30
31 fn post_removal(&self, _dir: &Path) -> Result<()> {
33 Ok(())
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
39pub enum State {
40 Unregistered,
42 Registered,
44 Bound,
46 Removed,
48}
49
50#[derive(Clone, Debug)]
52pub struct Status(FunctionDir);
53
54impl Status {
55 pub fn state(&self) -> State {
57 let inner = self.0.inner.lock().unwrap();
58 match (&inner.dir, inner.dir_was_set, inner.bound) {
59 (None, false, _) => State::Unregistered,
60 (None, true, _) => State::Removed,
61 (Some(_), _, false) => State::Registered,
62 (Some(_), _, true) => State::Bound,
63 }
64 }
65
66 #[cfg(feature = "tokio")]
70 pub async fn bound(&self) -> Result<()> {
71 loop {
72 let notifier = self.0.notify.notified();
73 match self.state() {
74 State::Bound => return Ok(()),
75 State::Removed => return Err(Error::new(ErrorKind::BrokenPipe, "gadget was removed")),
76 _ => (),
77 }
78 notifier.await;
79 }
80 }
81
82 #[cfg(feature = "tokio")]
84 pub async fn unbound(&self) {
85 loop {
86 let notifier = self.0.notify.notified();
87 if self.state() != State::Bound {
88 return;
89 }
90 notifier.await;
91 }
92 }
93
94 pub fn path(&self) -> Option<PathBuf> {
96 self.0.inner.lock().unwrap().dir.clone()
97 }
98}
99
100#[derive(Clone)]
104pub struct FunctionDir {
105 inner: Arc<Mutex<FunctionDirInner>>,
106 #[cfg(feature = "tokio")]
107 notify: Arc<tokio::sync::Notify>,
108}
109
110#[derive(Debug, Default)]
111struct FunctionDirInner {
112 dir: Option<PathBuf>,
113 dir_was_set: bool,
114 bound: bool,
115}
116
117impl fmt::Debug for FunctionDir {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 f.debug_tuple("FunctionDir").field(&*self.inner.lock().unwrap()).finish()
120 }
121}
122
123impl Default for FunctionDir {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl FunctionDir {
130 pub fn new() -> Self {
132 Self {
133 inner: Arc::new(Mutex::new(FunctionDirInner::default())),
134 #[cfg(feature = "tokio")]
135 notify: Arc::new(tokio::sync::Notify::new()),
136 }
137 }
138
139 pub(crate) fn set_dir(&self, function_dir: &Path) {
140 let mut inner = self.inner.lock().unwrap();
141 inner.dir = Some(function_dir.to_path_buf());
142 inner.dir_was_set = true;
143
144 #[cfg(feature = "tokio")]
145 self.notify.notify_waiters();
146 }
147
148 pub(crate) fn reset_dir(&self) {
149 self.inner.lock().unwrap().dir = None;
150
151 #[cfg(feature = "tokio")]
152 self.notify.notify_waiters();
153 }
154
155 pub(crate) fn set_bound(&self, bound: bool) {
156 self.inner.lock().unwrap().bound = bound;
157
158 #[cfg(feature = "tokio")]
159 self.notify.notify_waiters();
160 }
161
162 pub fn status(&self) -> Status {
164 Status(self.clone())
165 }
166
167 pub fn dir(&self) -> Result<PathBuf> {
169 self.inner
170 .lock()
171 .unwrap()
172 .dir
173 .clone()
174 .ok_or_else(|| Error::new(ErrorKind::NotFound, "USB function not registered"))
175 }
176
177 pub fn driver(&self) -> Result<OsString> {
179 let dir = self.dir()?;
180 let (driver, _instance) = split_function_dir(&dir)
181 .ok_or_else(|| Error::new(ErrorKind::InvalidData, "invalid function directory name"))?;
182 Ok(driver.to_os_string())
183 }
184
185 pub fn instance(&self) -> Result<OsString> {
187 let dir = self.dir()?;
188 let (_driver, instance) = split_function_dir(&dir)
189 .ok_or_else(|| Error::new(ErrorKind::InvalidData, "invalid function directory name"))?;
190 Ok(instance.to_os_string())
191 }
192
193 pub fn property_path(&self, name: impl AsRef<Path>) -> Result<PathBuf> {
195 let path = name.as_ref();
196 if path.components().all(|c| matches!(c, Component::Normal(_))) {
197 Ok(self.dir()?.join(path))
198 } else {
199 Err(Error::new(ErrorKind::InvalidInput, "property path must be relative"))
200 }
201 }
202
203 pub fn create_dir(&self, name: impl AsRef<Path>) -> Result<()> {
205 let path = self.property_path(name)?;
206 log::debug!("creating directory {}", path.display());
207 fs::create_dir(path)
208 }
209
210 pub fn create_dir_all(&self, name: impl AsRef<Path>) -> Result<()> {
212 let path = self.property_path(name)?;
213 log::debug!("creating directories {}", path.display());
214 fs::create_dir_all(path)
215 }
216
217 pub fn remove_dir(&self, name: impl AsRef<Path>) -> Result<()> {
219 let path = self.property_path(name)?;
220 log::debug!("removing directory {}", path.display());
221 fs::remove_dir(path)
222 }
223
224 pub fn read(&self, name: impl AsRef<Path>) -> Result<Vec<u8>> {
226 let path = self.property_path(name)?;
227 let res = fs::read(&path);
228
229 match &res {
230 Ok(value) => {
231 log::debug!("read property {} with value {}", path.display(), String::from_utf8_lossy(value))
232 }
233 Err(err) => log::debug!("reading property {} failed: {}", path.display(), err),
234 }
235
236 res
237 }
238
239 pub fn read_string(&self, name: impl AsRef<Path>) -> Result<String> {
241 let mut data = self.read(name)?;
242 while data.last() == Some(&b'\0') || data.last() == Some(&b' ') || data.last() == Some(&b'\n') {
243 data.truncate(data.len() - 1);
244 }
245
246 Ok(String::from_utf8(data).map_err(|err| Error::new(ErrorKind::InvalidData, err))?.trim().to_string())
247 }
248
249 pub fn read_os_string(&self, name: impl AsRef<Path>) -> Result<OsString> {
251 Ok(trim_os_str(&OsString::from_vec(self.read(name)?)).to_os_string())
252 }
253
254 pub fn write(&self, name: impl AsRef<Path>, value: impl AsRef<[u8]>) -> Result<()> {
258 let path = self.property_path(name)?;
259 let value = value.as_ref();
260 log::debug!("setting property {} to {}", path.display(), String::from_utf8_lossy(value));
261 crate::write_attr(&path, value)
262 }
263
264 pub fn symlink(&self, target: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
266 let target = self.property_path(target)?;
267 let link = self.property_path(link)?;
268 log::debug!("creating symlink {} -> {}", link.display(), target.display());
269 std::os::unix::fs::symlink(target, link)
270 }
271
272 pub fn dev_numbers(&self) -> Result<(u32, u32)> {
279 let dev = self.read_string("dev")?;
280 let Some((major, minor)) = dev.split_once(':') else {
281 return Err(Error::new(ErrorKind::InvalidData, "invalid device number format"));
282 };
283 let major = major.parse().map_err(|err| Error::new(ErrorKind::InvalidData, err))?;
284 let minor = minor.parse().map_err(|err| Error::new(ErrorKind::InvalidData, err))?;
285 Ok((major, minor))
286 }
287
288 pub fn dev_path(&self) -> Result<PathBuf> {
292 let (major, minor) = self.dev_numbers()?;
293 dev_path(major, minor)
294 }
295}
296
297pub fn dev_path(major: u32, minor: u32) -> Result<PathBuf> {
302 use std::os::{linux::fs::MetadataExt, unix::fs::FileTypeExt};
303
304 let target = rustix::fs::makedev(major, minor);
305
306 for entry in fs::read_dir("/dev")? {
307 let Ok(entry) = entry else { continue };
308 let Ok(meta) = entry.metadata() else { continue };
309 if meta.file_type().is_char_device() && meta.st_rdev() == target {
310 return Ok(entry.path());
311 }
312 }
313
314 Err(Error::new(ErrorKind::NotFound, format!("no device file found in /dev for {major}:{minor}")))
315}
316
317pub fn split_function_dir(function_dir: &Path) -> Option<(&OsStr, &OsStr)> {
319 let name = function_dir.file_name()?;
320 let name = name.as_bytes();
321
322 let dot = name.iter().enumerate().find_map(|(i, c)| if *c == b'.' { Some(i) } else { None })?;
323 let driver = &name[..dot];
324 let instance = &name[dot + 1..];
325
326 Some((OsStr::from_bytes(driver), OsStr::from_bytes(instance)))
327}
328
329type RemoveHandler = Arc<dyn Fn(PathBuf) -> Result<()> + Send + Sync>;
331
332static REMOVE_HANDLERS: OnceLock<Mutex<HashMap<OsString, RemoveHandler>>> = OnceLock::new();
334
335fn remove_handlers() -> MutexGuard<'static, HashMap<OsString, RemoveHandler>> {
337 let handlers = REMOVE_HANDLERS.get_or_init(|| Mutex::new(HashMap::new()));
338 handlers.lock().unwrap()
339}
340
341pub(crate) fn init_remove_handlers() {
343 static ONCE: Once = Once::new();
344 ONCE.call_once(|| {
345 register_remove_handlers();
346 });
347}
348
349pub fn register_remove_handler(
351 driver: impl AsRef<OsStr>, handler: impl Fn(PathBuf) -> Result<()> + Send + Sync + 'static,
352) {
353 remove_handlers().insert(driver.as_ref().to_os_string(), Arc::new(handler));
354}
355
356pub(crate) fn call_remove_handler(function_dir: &Path) -> Result<()> {
358 let Some((driver, _)) = split_function_dir(function_dir) else {
359 return Err(Error::new(ErrorKind::InvalidInput, "invalid function directory"));
360 };
361
362 let handler_opt = remove_handlers().get(driver).cloned();
363 match handler_opt {
364 Some(handler) => handler(function_dir.to_path_buf()),
365 None => Ok(()),
366 }
367}
368
369pub(crate) mod value {
371 use std::{
372 error::Error,
373 fmt,
374 fmt::Display,
375 io, mem,
376 sync::{mpsc, Mutex},
377 };
378
379 #[derive(Debug, Clone)]
381 pub struct AlreadySentError;
382
383 impl Display for AlreadySentError {
384 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
385 write!(f, "value already sent")
386 }
387 }
388
389 impl Error for AlreadySentError {}
390
391 #[derive(Debug)]
393 pub struct Sender<T>(Mutex<Option<mpsc::Sender<T>>>);
394
395 impl<T> Sender<T> {
396 pub fn send(&self, value: T) -> Result<(), AlreadySentError> {
400 match self.0.lock().unwrap().take() {
401 Some(tx) => {
402 let _ = tx.send(value);
403 Ok(())
404 }
405 None => Err(AlreadySentError),
406 }
407 }
408 }
409
410 #[derive(Debug, Clone)]
412 pub enum RecvError {
413 Empty,
415 Disconnected,
417 Taken,
419 }
420
421 impl Display for RecvError {
422 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
423 match self {
424 RecvError::Empty => write!(f, "value was not yet sent"),
425 RecvError::Disconnected => write!(f, "no value was sent"),
426 RecvError::Taken => write!(f, "value was taken"),
427 }
428 }
429 }
430
431 impl Error for RecvError {}
432
433 impl From<mpsc::RecvError> for RecvError {
434 fn from(_err: mpsc::RecvError) -> Self {
435 Self::Disconnected
436 }
437 }
438
439 impl From<mpsc::TryRecvError> for RecvError {
440 fn from(err: mpsc::TryRecvError) -> Self {
441 match err {
442 mpsc::TryRecvError::Empty => Self::Empty,
443 mpsc::TryRecvError::Disconnected => Self::Disconnected,
444 }
445 }
446 }
447
448 impl From<RecvError> for io::Error {
449 fn from(err: RecvError) -> Self {
450 match err {
451 RecvError::Empty => io::Error::new(io::ErrorKind::WouldBlock, err),
452 RecvError::Disconnected => io::Error::new(io::ErrorKind::BrokenPipe, err),
453 RecvError::Taken => io::Error::other(err),
454 }
455 }
456 }
457
458 #[derive(Default)]
460 enum State<T> {
461 Receiving(Mutex<mpsc::Receiver<T>>),
462 Received(T),
463 #[default]
464 Taken,
465 }
466
467 #[derive(Default)]
469 pub struct Receiver<T>(State<T>);
470
471 impl<T: fmt::Debug> fmt::Debug for Receiver<T> {
472 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
473 match &self.0 {
474 State::Receiving(_) => write!(f, "<uninit>"),
475 State::Received(v) => v.fmt(f),
476 State::Taken => write!(f, "<taken>"),
477 }
478 }
479 }
480
481 impl<T> Receiver<T> {
482 pub fn get(&mut self) -> Result<&mut T, RecvError> {
484 match &mut self.0 {
485 State::Receiving(rx) => {
486 let value = rx.get_mut().unwrap().try_recv()?;
487 self.0 = State::Received(value);
488 }
489 State::Taken => return Err(RecvError::Taken),
490 _ => (),
491 }
492
493 let State::Received(value) = &mut self.0 else { unreachable!() };
494 Ok(value)
495 }
496
497 #[allow(dead_code)]
499 pub fn wait(&mut self) -> Result<&mut T, RecvError> {
500 if let State::Receiving(rx) = &mut self.0 {
501 let value = rx.get_mut().unwrap().recv()?;
502 self.0 = State::Received(value);
503 }
504
505 self.get()
506 }
507
508 #[allow(dead_code)]
510 pub fn take(&mut self) -> Result<T, RecvError> {
511 self.get()?;
512
513 let State::Received(value) = mem::take(&mut self.0) else { unreachable!() };
514 Ok(value)
515 }
516 }
517
518 pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
520 let (tx, rx) = mpsc::channel();
521 (Sender(Mutex::new(Some(tx))), Receiver(State::Receiving(Mutex::new(rx))))
522 }
523}